Jump to content
Sign in to follow this  
rocket

Some Exciting Developments...

Recommended Posts

Where did you get your Shapefile from, please post data sources :)

http://www.linz.govt.nz/

Land Information New Zealand holds vast quantities of GIS data for New Zealand and it is all freely available.

Oh wait, you probably meant bushlurker... my bad... but LINZ is great for those making NZ maps. Or maybe, that's just me LOL

Edited by Rocket

Share this post


Link to post
Share on other sites

@OChristie

Try here for starters - though you can also make your own shapefiles by clicking around areas on your basemap and saving as .shp in Global Mapper, Microdem, ArcGIS, etc... (and thats the best way probably, if you're looking for high resolution)...

Select and download free geographic (GIS) data for any country in the world

or here...

Digital Chart of the World

or here...

Geocomm

(.E00 format loads in most GIS programs too)

Not nearly as good quality as the NZ or USA stuff though...

Digimap and Edina have good quality UK data, but you need to be a "member of an academic institution" to access it... (ie: a student or teacher), or you pay... (typical UK)!

USGS has quality data freely available for the US...

@Rocket

I've noticed a slight issue...

When you run the script several times, as you suggest, say with different trees for a more varied forest, the script seems to dump all three runs at pretty much the same point...

Like, one run each with 3 different types of tree at a density of 1 tree per 10m ideally should produce 3 randomly placed trees per 10m square, what it actually does is this...

too_close.jpg

Three trees pretty much on top of each other, then - 10m away, another 3 trees on top of each other, etc etc..

It might be better if there was a slightly bigger "scatter" in the placement - so when the script is told to place one tree in that 10m square, it picks a random place within the square - on the next run, the script does the exact same thing, but maybe uses a randomiser routine or something, so it's likely to pick a slightly different location within that 10m square each time...

Is that possible??

B

Edited by Bushlurker

Share this post


Link to post
Share on other sites

There was this random object placer in Visitor2

http://cross.kellys-heroes.eu/public/RandomObjectPlacer_V1.1.1.txt

perhaps it helps...

Rename ext to .vis to use with visitor.

great job on this... I've always dreamed of something like this...vegetation by colored mask file. Black & white should do just as fine too since I guess it is not possible to do it in color.

Cross

Edited by Cross

Share this post


Link to post
Share on other sites

Ive been playing around with this and its a very nice tool. Saves a ton of time especially in my case. I would say 35 % of my map is trees at 10240. So what I did was split the the mask into 4 pieces and imported 1 corner at a time. Visitor still fills the memory up. Does visitor reset memory after exiting and saving? So im assuming I would have to save and exit after every import?

Share this post


Link to post
Share on other sites
Ive been playing around with this and its a very nice tool. Saves a ton of time especially in my case. I would say 35 % of my map is trees at 10240. So what I did was split the the mask into 4 pieces and imported 1 corner at a time. Visitor still fills the memory up. Does visitor reset memory after exiting and saving? So im assuming I would have to save and exit after every import?

Interesting. I've done the exact same thing:cool: but I'm not to sure about the memory reset.

Share this post


Link to post
Share on other sites
Interesting. I've done the exact same thing:cool: but I'm not to sure about the memory reset.

I just tried it. After importing 70k objects my memory stayed at 1.37g and after I saved then exited then I reopened the memory was at 1.08. So it seems after every import I would exit and reopen.

I have a question.... What is the best way in making a tree mask. Im not talking about getting the trees on a mask. Thats the easy part. Whats the best way about making the different whites?

Ive been only able to use density 1 cause I have too much white. Ive played around with tons of different ways to make it spotty and less white but whats the best way?

Share this post


Link to post
Share on other sites

one thing u should keep in mind when using the maskmapper is u should always choose a new output file. If the output file u specify already exists it just appends it rather then overwriting it. May cause super large files to strangely appear.

Share this post


Link to post
Share on other sites

If I have the preferences set for the tree for different options for Randoms size, angle ect..... Will the maskmapper placethem random as well?

Share this post


Link to post
Share on other sites
If I have the preferences set for the tree for different options for Randoms size, angle ect..... Will the maskmapper placethem random as well?

Yes, it will.

Share this post


Link to post
Share on other sites

Presenting MaskMapper2 for the first time:

descx.jpg

Whats new:

- Obviously a complete GUI which makes working with it a whole lot easier. No need to retype countless times and everything is just much more visual.

- No need to use imageJ to convert to text images. Just load black/white or colour BMPs straight away.

- Less prone to square size errors since now u enter the physical size of your terrain as reference.

- Possibility to export up to 3 seperate vegetation masks in one go. With each of the channels in the BMP (Red, Green, Blue) containing independent masks.

An example:

Here's the image in Photoshop. Each channel hold a seperate mask (in the form of some text). The intensity of the white of course determines the final density of the vegetation.

psdemo.jpg

Saved as a normal BMP (24bit). Loaded into MaskMapper2:

mm2demo.jpg

Information is enteres into the multi-channel boxes. And the "Generate multi channel object lists" button is pressed. Three files with the type names are saved to the indicated folder. Here is the Visitor preview after a few minutes importing:

visdemo.jpg

NOTE: visitor object preview colours have nothing to do with the channels.

Expect to be out later today :)

Share this post


Link to post
Share on other sites

Soul Assasin..... You are amazing man! geez with all these things coming out from you and Rocket we all can be pumping out island in flippin days with this:yay::yay::yay:

You guys are bad ass for this!:cool:

Share this post


Link to post
Share on other sites

Soul and Rocket, do you guys have PayPal accounts set up? I would like to donate a little $ to show my appreciation of your work.

Share this post


Link to post
Share on other sites
Presenting MaskMapper2 for the first time

Looks very good, nice job!

Still Open Source so others can study the code?

Share this post


Link to post
Share on other sites
Looks very good, nice job!

Still Open Source so others can study the code?

The principle is still the same as the first code. There is just no point posting this one cuz now its a few files mainly because of the GUI. Also the GUI is wxWidgets which will not apply for people who dont use them in their coding. The core algorithm though is still this way:

if (WxSaveObjList->ShowModal() == wxID_OK)
{
       WxProgressDialog->Show(true);
       ofstream fout(WxSaveObjList->GetPath(),ios::trunc);
    int imageWidth = maskImage->GetWidth();
       int landWidth = landMassWidth->GetValue();
       float square = (float)landWidth/(float)imageWidth;

   	unsigned char* imageData = maskImage->GetData();

   	int x = 0;
   	int y = imageWidth - 1;

   	int densityVal = density->GetValue();

   	float yPos;
   	float xPos;
   	float xPosObj;
   	float yPosObj;
   	float angObj;
   	float numObjectsFloat;
   	float randX;
   	int numObjectsInt;
   	int pixCount = 0;
   	int num = 0;

   	while (y>=0)
    {
   		yPos = y * square;
           while (x<imageWidth)
           {
               xPos = x * square;
   		    int data = imageData[pixCount];
   			numObjectsFloat = (float)data/255 * densityVal;
   			numObjectsInt = (int)numObjectsFloat;
   			for (int j = 1 ; j <= numObjectsInt; j++)
   			{
   				num++;
   			}
   			x += 1;
   			pixCount += 3;
   		}
   		y -= 1;
   		x = 0;
    }
   	y = imageWidth - 1;
   	x = 0;
   	int num1 = 0;
   	pixCount = 0;
   	while (y>=0)
   	{
   		yPos = y * square;
           while (x<imageWidth)
           {
               xPos = x * square;
   		    int data = imageData[pixCount];
   			numObjectsFloat = (float)data/255 * densityVal;
   			numObjectsInt = (int)numObjectsFloat;
   			for (int j = 1 ; j <= numObjectsInt; j++)
   			{
                   num1++;
   				randX = (float)rand()/(float)RAND_MAX;
   				xPosObj = xPos + ( rand() % (int)square) + randX;
   				yPosObj = yPos + ( rand() % (int)square) + randX;
   				angObj = randX*360 - 180;
   				fout << "\"" << objectType->GetLineText(0) << "\";" << xPosObj << ";" << yPosObj << ";0;" << angObj << ";" << endl;
                   wxString progressString;
                   float percent = (float)num1/(float)num*100;
                   progressString << "Generating object " << num1 << "/" << num;
                   WxProgressDialog->Update((int)percent,progressString,NULL);

   			}
   			x += 1;
   			pixCount += 3;
   		}
   		y -= 1;
   		x = 0;
   	}
   	fout.close();
   	WxProgressDialog->Show(false);
   	wxString finalString;
   	finalString << "Saved " << num1 << " object(s) \"" << objectType->GetLineText(0) << "\" successfully."; 
   	WxStatusBar1->SetStatusText(finalString,1);
   }

multi-channel export:

int imageWidth, landWidth, x, y, densityVal, numObjectsInt, pixCount, num, num1;
   float square, xPos, yPos, xPosObj, yPosObj, angObj, numObjectsFloat, randX, percent;
   wxString folderPath, filePathR, filePathG, filePathB, objType;

   wxString filePathArray[3];

if (getSaveDir->ShowModal() == wxID_OK)
{
       folderPath = getSaveDir->GetPath();
       filePathR = rChannelType->GetLineText(0);
       filePathG = gChannelType->GetLineText(0);
       filePathB = bChannelType->GetLineText(0);

       filePathArray[0] = folderPath+"\\"+filePathR+".txt";
       filePathArray[1] = folderPath+"\\"+filePathG+".txt";
       filePathArray[2] = folderPath+"\\"+filePathB+".txt";

       for (int a = 0; a <= 2; a++)
       {
           WxProgressDialog->Show(true);
           ofstream fout(filePathArray[a],ios::trunc);
   	    imageWidth = maskImage->GetWidth();
           landWidth = landMassWidth->GetValue();
           square = (float)landWidth/(float)imageWidth;

       	unsigned char* imageData = maskImage->GetData();

       	x = 0;
       	y = imageWidth - 1;

       	densityVal = density->GetValue();

           pixCount = a;
       	num = 0;

       	while (y>=0)
   	    {
       		yPos = y * square;
               while (x<imageWidth)
               {
                   xPos = x * square;
       		    int data = imageData[pixCount];
       			numObjectsFloat = (float)data/255 * densityVal;
       			numObjectsInt = (int)numObjectsFloat;
       			for (int j = 1 ; j <= numObjectsInt; j++)
       			{
       				num++;
       			}
       			x += 1;
       			pixCount += 3;
       		}
       		y -= 1;
       		x = 0;
   	    }
       	y = imageWidth - 1;
       	x = 0;
       	num1 = 0;
       	pixCount = a;

       	switch (a)
       	{
               case 0:
                   objType = rChannelType->GetLineText(0);
                   break;
               case 1:
                   objType = gChannelType->GetLineText(0);
                   break;
               case 2:
                   objType = bChannelType->GetLineText(0);
                   break;
               default:
                   objType = rChannelType->GetLineText(0);
                   break;
           }


       	while (y>=0)
       	{
       		yPos = y * square;
               while (x<imageWidth)
               {
                   xPos = x * square;
       		    int data = imageData[pixCount];
       			numObjectsFloat = (float)data/255 * densityVal;
       			numObjectsInt = (int)numObjectsFloat;
       			for (int j = 1 ; j <= numObjectsInt; j++)
       			{
                       num1++;
       				randX = (float)rand()/(float)RAND_MAX;
       				xPosObj = xPos + ( rand() % (int)square) + randX;
       				yPosObj = yPos + ( rand() % (int)square) + randX;
       				angObj = randX*360 - 180;

       				fout << "\"" << objType << "\";" << xPosObj << ";" << yPosObj << ";0;" << angObj << ";" << endl;
                       wxString progressString;
                       percent = (float)num1/(float)num*100;
                       progressString << "File " << (a+1) << " of 3. Generating object " << num1 << "/" << num;
                       WxProgressDialog->Update((int)percent,progressString,NULL);
       			}
       			x += 1;
       			pixCount += 3;
       		}
       		y -= 1;
       		x = 0;
       	}
       	fout.close();
       	WxProgressDialog->Show(false);
       	wxString finalString;
       	finalString << "Saved " << num1 << " object(s) \"" << objType << "\" successfully."; 
       	WxStatusBar1->SetStatusText(finalString,1);
       }
   }

beyond that Im afraid the rest of the code doesnt make any sence :P

Share this post


Link to post
Share on other sites

Mate!! ..... thats just Awesome !

With GUI tools like this the whole Terrain making exercise could become a breeze!

I dream of making tools like this ... except I'm crap with the 2d and 3d maths lol.

Share this post


Link to post
Share on other sites

Well, the prospect is entrancing but as I am still an old dumb noob, I am unable to get any vegetation from my outputfile.txt, I am generating extrahuge files from my .bmp pics and importing the stuff in Visitor ends every times with an out of memory error message.

Could you explain me some points :

- what is density?

- what is the relation between the grey level and the density ?

- is the .exe populating white or black areas ?

- is density = 1 a valid value ?

Share this post


Link to post
Share on other sites

Here's a quick and dirty explanation:

imagine you have a 25x25 km area (25000m). The mask BMP that you are making will be pulled over it. Each pixel in that bmp defines what is happening in that square. If your bmp texture is 2500x2500 pixels then the square size we are talking about is 25000/2500 = 10 m. So each pixel in the bmp defines a 10x10 m physical square on your map.

Now the bmp can contain pixels from pure black to pure white (all shades of grey). Black = no vegetation, white = as much vegetation as defined by the density amount. Shades of grey are in between respectively. So for example:

Mask Size:

2500

Square Size:

10

Density:

7

Would mean, where in the mask bmp you have a white pixel the corresponding land square will have 7 trees. If the pixel you have is 50% grey then you will have 3 trees there.

Thats it :)

The extra huge files are probably explained by u outputting to the same file every time you try. Try saving to another file or reducing density.

The GUI should make things abit more intuitive.

Share this post


Link to post
Share on other sites

So the "density" parameter you are typing in the tool is not the final density value, this final density is a combination between "density" from the pic and this "density" param, so if the pixel is 97% and density is 1, there will be no object on map ?

Share this post


Link to post
Share on other sites

most likely yes as 1*0.97 = 0.97 and in C++ when this gets converted into an integer it is 0. So when using density 1 better only use straight black/white.

Share this post


Link to post
Share on other sites

Hello all,

the original plan was to get Rocket to release it but he's now been AWOL a few days so I decided to release myself:

http://sparrowstudio.net/armavdv/software/maskMapper2.rar

Features:

- no need to convert to text images anymore. Just load in the BMP masks.

- now comes with an intuitive GUI interface. No need to retype everything many times.

- a little better optimized and organized. Now you use terrain size to calculate square sizes so its less error prone.

- preview maps

- estimate number of objects

- option to generate 3 object files at a time using the separate channels.

The tutorial will be updated once i hear from Rocket.

Enjoy.

Share this post


Link to post
Share on other sites
computers sadly cannot produce truly random numbers, especialy floating point numbers.

You can't seed the randomizer with user-generated input that would be different on a daily basis? "What day is it?" Seed Number then generated from adding up the numerological value of text entered?

File name, for example. Version #.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×