Import GeoJSON files from potrace

Let us know if you have a nice R.U.B.E script to share!
Post Reply
rokus
Posts: 4
Joined: Mon Apr 06, 2015 1:11 pm

Import GeoJSON files from potrace

Post by rokus »

Hi,

for a platformer game, i create my levels as pixel graphic files. Since the tracing algorithm for images in RUBE is not able to produce correct fixtures out of my bitmaps, i wrote a small script that imports GeoJSON files that i get from potrace. Potrace is a very good bitmap-to-vector software, available for all major OSes.

My workflow, so you get an idea how to use it:
- create bmp with the desired level layout
- run "potrace -i -b geojson level.bmp" on it; that creates a new file level.json
- execute my rubescript, select the .json-file from potrace
- insert items, enemies etc. in RUBE
- load the RUBE json in my game.

Limitations:
- since RUBE doesn't support holes in vertices, GeoJSON files with holes won't work.
- the coordinates in the GeoJSON file refer to pixels, not Box2D meter. The fixtures created will be very large, you have to scale them down afterwards.
- i haven't tested the script thoroughly, it may or may not work for your files. I use it only with my level files and with potrace and no other GeoJSON file.
- the program can crash, if poly2tri get's overstrained by the imported polygons.

[It would be supercool if RUBE would support holes in fixtures and/or the potrace library (it's GPLed, don't know if that's the problem).] ;)

[and my scripting style is bad. sorry.]

Code: Select all

void main() 
{
	string filename = queryOpenFile("*");
	string filecontent = readFile(filename);
	vec2[][] polygons = parseGeoJSON(filecontent);
	print (polygons.length() + " polygons found");

	body b = addBody(-1, '{"type":"static","awake":true}');
	b.setPos( cursor() );

	for (uint i = 0; i < polygons.length(); ++i)
	{
		string xValues, yValues;
		for (uint j = 0; j < polygons[i].length()-1; j++) //last coordinate is first coordinate again, so we skip it
		{
			xValues += polygons[i][j].x;
			yValues += polygons[i][j].y;

			if (j < polygons[i].length() - 2)
			{
				xValues += ",";
				yValues += ",";
			}
		}

	if (xValues.isEmpty() || yValues.isEmpty()) continue;
	string fixtureDef = '{"density":1,"shapes":[{"radius":0,"type":"polygon"}],"friction":0.2,"vertices":{"x":['+xValues+'],"y":['+yValues+']}}';
	b.addFixture(-1, fixtureDef);
	xValues = ""; yValues = "";

	}

	print("ok");
}

uint filePointer = 0;

vec2[][] parseGeoJSON(string jsonfilecontent)
{
	vec2[][] polygons;
	while (filePointer < jsonfilecontent.length())
	{
		string char = 	readChar(jsonfilecontent);

		if (char == "\"")
		{ 
				string word = readWord(jsonfilecontent, "\"");
				if (word == "coordinates") 
				{
					polygons = readPolygon(jsonfilecontent, polygons);
				}
		}
	}
	return polygons;
}

string readChar(string filecontent)
{
	if (filePointer >= filecontent.length())
	{
		print("end of file");
		return "";
	}
	//skip blanks und newlines
	string ret = " ";
	while (ret == " " || ret == "\n")
	{
		filePointer++;
		ret = filecontent.substr(filePointer-1,1);
	}
	return filecontent.substr(filePointer-1,1);
}

string readWord(string filecontent, string delim)
{
	string word = "";
	string char = readChar(filecontent);
	while (char != delim)
	{
		word += char;
		char = readChar(filecontent);
	}
	return word;
}

vec2[][] readPolygon(string filecontent, vec2[][] polys)
{
	int polycount = 0;

	// fast forward to beginning of polygon
	while (readChar(filecontent) != "[") continue;

	vec2[] polygon;
	//readCoordinate reads whole coord-block: xx.0,yy.0] incl. closing bracket
	while (readChar(filecontent) != "]") //... and that's why this ] marks the end of the polygon
	{
		polygon.insertLast(readCoordinate(filecontent));
		polycount++;
	}

	polys.insertLast(polygon);

	if (readChar(filecontent) == ",") // multiple polygons in one definition
		return readPolygon(filecontent, polys);
	else  return polys;
}

vec2 readCoordinate(string filecontent)
{
	readChar(filecontent); // skip "[" 
	string word = readWord(filecontent, "]");

	vec2 coordinate;
	string[] coordinates = word.split(",");
	if (coordinates.length() != 2) return coordinate;

	float x = parseFloat(coordinates[0]);
	float y = parseFloat(coordinates[1]);

	coordinate.set(x,y);
	return coordinate;
}
iforce2d
Site Admin
Posts: 861
Joined: Sat Dec 22, 2012 7:20 pm

Re: Import GeoJSON files from potrace

Post by iforce2d »

Thanks for this, very nice!
Post Reply