Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2430

Warning: implode(): Argument must be an array in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3384

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3448

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2430

Warning: implode(): Argument must be an array in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3384

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3448

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2430

Warning: implode(): Argument must be an array in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3384

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3448

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2430

Warning: implode(): Argument must be an array in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3384

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3448

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2430

Warning: implode(): Argument must be an array in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3384

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3448

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2430

Warning: implode(): Argument must be an array in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3384

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3448

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2430

Warning: implode(): Argument must be an array in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3384

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3448

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2058

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 2430

Warning: implode(): Argument must be an array in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3384

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3407

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3448

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3500

Warning: array_keys() expects parameter 1 to be array, null given in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

Warning: Invalid argument supplied for foreach() in /home/pensand2/public_html/wp/wp-content/plugins/wp-syntax/geshi/geshi.php on line 3644

stampa questo articolo
In questi giorni ho riscontrato un problema con mongoDB versione 2.4 ed i nuovi oggetti geometrici ovvero con l’indice 2dsphere e l’oggetto geometrico “LineString“.

Avevo parlato di mongoDB 2.4 e nuove funzionalità sugli oggetti geometrici in questo post.

Descrizione del problema

In locale prendo le coordinate gps e le invio poi ad un rest webservice node.js che fa la insert in mongoDB delle coordinate sotto forma di linestring (spezzata), strutturate secondo le specifiche mongoDB 2.4 per gli oggetti geometrici ovvero

1
2
3
{ loc : { type : "LineString" ,
          coordinates : [ [12.0991736,42.4245143],[12.0991226,42.42456500000001] ]
} }

Il problema è che a volte la insert va a buon fine altre volte ritorna il seguente errore:

Can’t extract geo keys from object, malformed geometry?

Sembrerebbe che mongoDB non riconosca i valori inseriti come coordinate corrette o comunque non riconosca l’oggetto “LineString”.

Ho cercato un pochino sul web ma non ho trovato nulla, probabilmente è troppo “giovane” la funzionalità spaziale con il nuovo indice 2dsphere per avere sufficiente letteratura.

Il sorgente mongoDB

Sono quindi arrivato al sorgente di mongoDB per cercare di capire qualcosa.

https://github.com/mongodb/mongo/blob/master/src/mongo/db/geo/s2index.cpp

alla riga 281 (del sorgente git) c’è la stringa dell’errore che mi esce quando faccio la “insert”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// We only support GeoJSON polygons.  Why?:
// 1. we don't automagically do WGS84/flat -> WGS84, and
// 2. the old polygon format must die.
if (GeoParser::isGeoJSONPolygon(obj)) {
	S2Polygon polygon;
	GeoParser::parseGeoJSONPolygon(obj, &polygon);
	keysFromRegion(&coverer, polygon, &cells);
} else if (GeoParser::parseLineString(obj, &line)) {
	keysFromRegion(&coverer, line, &cells);
} else if (GeoParser::parsePoint(obj, &point)) {
	S2CellId parent(point.id().parent(_params.finestIndexedLevel));
	cells.push_back(parent.toString());
} else {
	uasserted(16572, "<span style="color: #ff0000;">Can't extract geo keys from object, malformed geometry?</span>:"
					 + obj.toString());
}

Il metodo è il seguente:

1
GeoParser::parseLineString(obj, &amp;line)

che si trova in

https://github.com/mongodb/mongo/blob/master/src/mongo/db/geo/geoparser.cpp

1
2
3
4
5
bool GeoParser::parseLineString(const BSONObj &amp;obj, S2Polyline *out) {
	if (!isGeoJSONLineString(obj)) { return false; }
	parseGeoJSONLineString(obj, out);
	return true;
}

che a sua volta richiama “isGeoJSONLineString

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
bool GeoParser::isGeoJSONLineString(const BSONObj&amp; obj) {
	BSONElement type = obj.getFieldDotted(GEOJSON_TYPE);
	if (type.eoo() || (String != type.type())) { return false; }
	if (GEOJSON_TYPE_LINESTRING != type.String()) { return false; }
 
	if (!crsIsOK(obj)) {
		warning() &lt;&lt; "Invalid CRS: " &lt;&lt; obj.toString() &lt;&lt; endl;
		return false;
	}
 
	BSONElement coordElt = obj.getFieldDotted(GEOJSON_COORDINATES);
	if (coordElt.eoo() || (Array != coordElt.type())) { return false; }
 
	const vector&amp; coordinateArray = coordElt.Array();
	if (coordinateArray.size() &lt; 2) { return false; }
	if (!isArrayOfCoordinates(coordinateArray)) { return false; }
	vector vertices;
	parsePoints(obj.getFieldDotted(GEOJSON_COORDINATES).Array(), &amp;vertices);
	return S2Polyline::IsValid(vertices);
}

Analizzando questo metodo si nota subito come ci siano moltissimi controlli sulla correttezza della “LineString” ossia dell’insieme di punti che compongono la spezzata.

Questo un esempio di json reale che ritorna l’errore

1
2
3
{ loc : { type : "LineString" ,
          coordinates : [ [12.0991736,42.4245143],[12.0991226,42.42456500000001],[12.0991525,42.42452249999999],[12.0991435,42.4244968],[12.0991489,42.4245177],[12.0991439,42.4245229],[12.0991472,42.4245192],[12.0991503,42.42452180000001],[12.0991484,42.4245192],[12.0991351,42.4244986],[12.099134,42.4244971],[12.0991409,42.4245173],[12.0991409,42.4245173],[12.0991423,42.424527],[12.0991347,42.4244803],[12.0991462,42.42451519999999],[12.0991441,42.4245188],[12.0991435,42.4245191],[12.0991442,42.42451519999999],[12.0991452,42.424515],[12.0991433,42.4245182],[12.0991429,42.4245156],[12.0991463,42.424517],[12.0991086,42.4245464] ]
} }

I punti sono, o almeno sembrano, essere corretti. Sono espressi in coordinate standard WGS84 lette direttamente dal GPS e correttamente strutturati secondo lo standard mongoDB 2.4.

Dove sta quindi l’errore?

Dopo molto “spippolamento” e confrontandomi con i ragazzi della community G+ “Italian Developers” sono arrivato a capire che per mongoDB quell’insieme di coordinate non è una “LineString” corretta perché ad un certo punto dell’array ci sono due coppie di coordinate uguali.

Queste le due coppie incriminate:

1
[12.0991409,42.4245173],[12.0991409,42.4245173]

Le coordinate, ovvio, me le ha date il GPS per cui il problema potrebbe essere molto più frequente del previsto qualora si tracciassero coordinate stando fermi.

La soluzione

Per risolvere basta verificare che una qualsiasi coppia n-1 sia diversa dalla coppia n, nel caso siano uguali non inserire nell’array la seconda coppia n ( o togliere la n-1 già inserita ).

Ho verificato che il problema si verifichi solo per le coppie contigue, se ci sono coppie uguali non contigue il problema non si presenta.

Il controllo è fatto dal seguente metodo (generico per ogni polilinea):

1
S2Polyline::isValid(vertices)

Una polyline in coordinate sferiche non ammette archi di lunghezza zero e orientamento 180°, che si traduce in due punti consecutivi sovrapposti.

Questo il codice :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
bool S2Polyline::IsValid(vector const&amp; v) {
  // All vertices must be unit length.
  int n = v.size();
  for (int i = 0; i &lt; n; ++i) {
    if (!S2::IsUnitLength(v[i])) {
      S2LOG(INFO) &lt;&lt; "Vertex " &lt;&lt; i &lt;&lt; " is not unit length";
      return false;
    }
  }
 
  // Adjacent vertices must not be identical or antipodal.
  for (int i = 1; i &lt; n; ++i) {
    if (v[i-1] == v[i] || v[i-1] == -v[i]) {
      S2LOG(INFO) &lt;&lt; "Vertices " &lt;&lt; (i - 1) &lt;&lt; " and " &lt;&lt; i
                &lt;&lt; " are identical or antipodal";
      return false;
    }
  }
  return true;
}

Come si vede è espressamente commentato che “Vertici adiacenti non devono essere identici o agli antipodi

Conclusioni

Va benissimo l’errore perché effettivamente da specifiche la linestring non era corretta, però perché non dettagliare meglio il messaggio?

C’è una bella differenza tra :

“Can’t extract geo keys from object, malformed geometry?”

e

“Adjacent vertices must not be identical or antipodal”

Magari mi sarei risparmiato tutto questo tempo per cercare di risolvere il problema.

Ho pensato di farci un post perché potrebbe capitare anche ad altri sviluppatori non appena la nuova release di mongoDB 2.4 diverrà ufficiale sulle varie piattafome cloud.

Che te ne pare dell’articolo? Ti era mai capitata una cosa simile? Pensi che ti potrebbe essere di aiuto?

Potrebbe interessarti anche ...

3 Commenti

  1. omioddio!

    sono praticamente settimane che non riuscito a capire da dove cacchio uscira fuori quel problema!! su alcune banalissime linestring che avevo gia importato e sulle quali stavo cercando di applicare un indiche che ovviamente dava sempre QUEL MALEDETTO MESAGGIO INCOMPRENSIBILE!!

    GRAZIE GRAZIE GRAZIE!!
    se capito a Viterbo di devo come minimo ofrire una Birra!!
    Stefano

LASCIA UN COMMENTO

Please enter your comment!
Please enter your name here