How to create a world map using C language? - c

How to create a world map using C language?
Here, I want to generate a 1000*1000 two dimensional array of world map. Within the array, the land part is marked with value 1 and the sea part is marked with value 0. Is there any simple way to create?

Obviously, there's no algorithm which describes the shape of the coastline of the continents ;)
But you could use e.g. Smrender (http://www.abenteuerland.at/smrender/), feed it with the coastline of e.g. OpenStreetMap or Naturalearthdata and a single rule. Let it create a PNG image with 1000x1000 pixels.
EDIT:
With ImageMagick (convert) you can directly convert a PNG into a C header file as an array.
Go to Openstreetmap.org (or Googlemaps), zoom out until you see the whole world, make a screenshot, open it in your favorite image manipulation program and cut and resize it to 1000x1000, then run convert input.png output.h.
Bernhard

I wrote a answer in game development some hours ago that can help you, heres the topic, it's written in javascript, but it won't be hard to translate to c.
In the example you fill the whole map of 0's and then you trace a path randomly, if you want to smooth the map later you can make a snippet that loops all the watter tiles and converts them to land if there are 3 or more land tiles adjacent to it, do it 40-60 times and you will get a smoother shore and no "holes" in the continent.
EDIT
Updating the answer with a demo in C.
I've not tested it, but if you include the headers and checks the code, this is the answer.
//Create and populate the map
int mapsize = 100;
int map[mapsize*mapsize];
for(int t = 0; t < mapsize*mapsize; t++) map[t] = 0;
//make the path
int currPos[2] = {0,50};
map[currPos[0]+(currPos[1]*mapSize)] = 1;
int landTiles = 20000;
for(var l = 0; l < landTiles; l++){
int dir[2] = {RANDOM_BETWEEN_-1_AND_1, RANDOM_BETWEEN_-1_AND_1};
int next[2] = {currPos[0]+dir[0], currPos[1]+dir[1]};
map[next[0]+(next[1]*mapSize)] = 1;
currPos = next;
}
//Draw the map
for(var row = 0; row < mapSize; row++){
for(var col = 0; col < mapSize; col++){
cout << map[col+(row*mapSize)];
}
cout << endl;
}

You could have some program or script (taking as input some representation of some image of the Earth) which generates a long C file like
const char map[1000][1000] = {
{'0', '1', //.... etc for the first fow
},
{'0', '0', '0', '1', //... etc
}
/// etc for other rows
};
See also XBM for an example.

Related

Inverting a PGM's Color Values Distorts the Image

My goal is to read in a PGM image and produce an image with inverted color values. But when I put in this image, I get back this image. I'm programming in C, using Eclipse and MinGW GCC on Windows 7 (64-bit). Why is the image getting so drastically distorted?
int complement(PGMImage *img) {
int i, j;
// set up new PGM to copy onto
PGMImage* comImg = (PGMImage*)malloc(sizeof(PGMImage));
(*comImg).width = (*img).width;
(*comImg).height = (*img).height;
// invert each pixel
for(i = 0; i <= (*img).width; i++) {
for(j = 0; j <= (*img).height; j++) {
// set inverted value for each new pixel
(*comImg).data[i][j].red = abs((*img).maxVal - (*img).data[i][j].red);
(*comImg).data[i][j].green = abs((*img).maxVal - (*img).data[i][j].green);
(*comImg).data[i][j].blue = abs((*img).maxVal - (*img).data[i][j].blue);
}
}
// save a copy of the complement image
save("C:\\image_complement.pgm", comImg);
printf("A copy of your image has been saved as \"C:\\image_complement.pgm\"\n\n");
void free(comImg);
return 0;
}
I'm not sure, but I would suspect the outer array index of your image to be the line and the inner to be the column. Thus I would expect that i should run to (*img).height and j to (*img).width.
I think <= should be < in both of your loops. With the revised image, from the comments to the other answer, it looks like it's "stepping over the edge" on each row.
Um, a pgm is a graymap, right? What does "red" "green" and "blue" mean?

Rotating a 2D PGM Image Array in C

I am working on a homework project to rotate a simple 2D array holding RGB values for a PGM file.
I've read many posts in these forums about how to do this in C, and I've almost got it working. My output file has the correct dimensions and is rotated, but there is a thick black border around the top and sides. I just can't figure out what I'm doing wrong.
Any help would be greatly appreciated!
I modified the code presented here to get started, and this is the rotate90 function I'm working on now:
PGMImage* rotate90(PGMImage *old_img)
{
int x, y;
PGMImage *new_img = malloc(sizeof(PGMImage));
new_img->maxVal = old_img->maxVal;
new_img->width = old_img->height;
new_img->height = old_img->width;
for (x = 0; x < old_img->width; x++)
{
for (y = 0; y < old_img->height; y++)
{
new_img->data[old_img->height - 1 - y][x].r = old_img->data[x][y].r;
new_img->data[old_img->height - 1 - y][x].g = old_img->data[x][y].g;
new_img->data[old_img->height - 1 - y][x].b = old_img->data[x][y].b;
}
}
return new_img;
}
void main()
{
PGMImage* img = malloc(sizeof(PGMImage));
getPGMfile("columns.pgm", img);
save("columns_new.ppm", rotate90(img));
}
The save() and getPGMfile() functions work perfectly on their own.
It's only when I pass the result of my rotate90() function to save() that I get the funky results.
How about trying memcpy(new_img, old_img, sizeof(PGMImage) after the malloc statement. Maybe some other attributes besides width and height are not initialized. And also, if the data variable is a pointer, did you malloc a piece of memory for data for the new_img object?

Creating an If statement for an entire array

So here is my situation. I'm new to programming and I've just started making a very, very basic platform game. And I mean literally a game with platforms.
I've got my character in and jumping about and I've created my platforms as an array. This was so that I could put them all side by side at the bottom. Now there is other ways I can do this to get round the problem but I wanted to find out how to do it for an array.
So I've got my character falling with this
kirby.yVelocity += 1.0f
Which is all fine but I want his yVelocity to go to 0.0f when he hits any of the platforms in the array.
So I tried this piece of code
if (plat[i].drawRect.Intersects(kirby.drawRect))
{
kirby.yVelocity = 0.0f
}
which I thought would work but it gives me an error for the [i] saying that it isn't applicable in this context.
few notes:
kirby is my character name, drawRect is the definition for Rectangle, plat is my Platform array which consists of 13 platforms.
Thanks to anyone who can help
Update
The problem is any variation of plat.drawRect or plat[i].drawRect don't work. Here is all my code relating to the platform arrays.
struct Platform
{
public Texture2D txr;
public Rectangle drawRect;
}
Platform[] plat;
plat = new Platform[13];
for (int i = 0; i < plat.Length; i++)
{
plat[i].txr = Content.Load<Texture2D>("platform");
plat[i].drawRect = new Rectangle(i * plat[i].txr.Width, 460, plat[i].txr.Width, plat[i].txr.Height);`
}
for (int i = 0; i < plat.Length; i++)
{
spriteBatch.Draw(plat[i].txr, plat[i].drawRect, Color.White);
}
spriteBatch.End();
Seems like you have to add a for loop, to loop over the platforms. Maybe like this:
for(Platform : plat){
if (platform.drawRect.Intersects(kirby.drawRect)){
kirby.yVelocity = 0.0f;
}
}
Here, I'm assuming you're using Java and Platform is the class of your plat-array, which has class List<Platform>.

How to draw a polygon from a set of unordered points

Currently, I am using a convex hull algorithm to get the outer most points from a set of points randomly placed. What I aim to do is draw a polygon from the set of points returned by the convex hull however, when I try to draw the polygon it looks quite strange.
My question, how do I order the points so the polygon draws correctly?
Thanks.
EDIT:
Also, I have tried sorting using orderby(...).ThenBy(...) and I cant seem to get it working.
Have you tried the gift wrapping algorithm ( http://en.wikipedia.org/wiki/Gift_wrapping_algorithm)? This should return points in the correct order.
I had an issue where a random set of points were generated from which a wrapped elevation vector needed a base contour. Having read the link supplied by #user1149913 and found a sample of gift-wrapping a hull, the following is a sample of my implementation:
private static PointCollection CalculateContour (List<Point> points) {
// locate lower-leftmost point
int hull = 0;
int i;
for (i = 1 ; i < points.Count ; i++) {
if (ComparePoint(points[i], points[hull])) {
hull = i;
}
}
// wrap contour
var outIndices = new int[points.Count];
int endPt;
i = 0;
do {
outIndices[i++] = hull;
endPt = 0;
for (int j = 1 ; j < points.Count ; j++)
if (hull == endPt || IsLeft(points[hull], points[endPt], points[j]))
endPt = j;
hull = endPt;
} while (endPt != outIndices[0]);
// build countour points
var contourPoints = new PointCollection(points.Capacity);
int results = i;
for (i = 0 ; i < results ; i++)
contourPoints.Add(points[outIndices[i]]);
return contourPoints;
}
This is not a full solution but a guide in the right direction. I faced a very similar problem just recently and I found a reddit post with an answer (https://www.reddit.com/r/DnDBehindTheScreen/comments/8efeta/a_random_star_chart_generator/dxvlsyt/) suggesting to use Delaunay triangulation which basically returns a solution with all possible triangles made within the data points you have. Once you have all possible triangles, which by definition you know won't result on any overlapped lines, you can chose which lines you use which result on all nodes being connected.
I was coding my solution on python and fortunately there's lots of scientific libraries on python. I was working on a random sky chart generator which would draw constellations out of those stars. In order to get all possible triangles (and draw them, just for fun), before going into the algorithm to draw the actual constellations, all I had to do was this:
# 2D array of the coordinates of every star generated randomly before
points = list(points_dict.keys())
from scipy.spatial import Delaunay
tri = Delaunay(points)
# Draw the debug constellation with the full array of lines
debug_constellation = Constellation(quadrants = quadrants, name_display_style = config.constellation_name_display_style)
for star in available_stars:
debug_constellation.add_star(star)
for triangle in tri.simplices:
star_ids = []
for index in triangle:
star_ids.append(points_dict[points[index]].id)
debug_constellation.draw_segment(star_ids, is_closed = True)
# Code to generate the image follows below
You can see the full implementation here: fake_sky_chart_generator/fake_libs/constellation_algorithms/delaunay.py
This is the result:

Printing Canvas to image silverlight

I have scuccesfully added canvas to bitmap using WritebleBitmap class and then trying to use the bitmap to save image on client system through SaveFileDilogue. I am using the method of FluxJpegCore image encoding where we use raster arrays to generate image pixel-wise.
Below is the part of the code which does the job.
byte[][,] raster = new byte[bands][,];
for (int i = 0; i < bands; i++)
{
raster[i] = new byte[width, height];
}
for (int row = 0; row < height; row++)
{
for (int column = 0; column < width; column++)
{
int pixel = bitmap.Pixels[width * row + column];
raster[0][column, row] = (byte)(pixel >> 16);
raster[1][column, row] = (byte)(pixel >> 8);
raster[2][column, row] = (byte)pixel;
}
}
All goes fine with image saving, however when i zoom the image and then print it, the code fails at the line "raster[i] = new byte[width, height];". System out of memory error is raised. Can anyone help me to find the solution on this?
I'm not sure there is a solution to be had. You have 3 arrays that each need a contiguous 163MB block of memory. The problem will be that the process does not have 3 such address blocks available that are that size.
Bear in mind also that the bitmap.Pixels will be an array 653MB big.
Your only real hope(s) would be to
Use the app OOB, hopefully VM fragmentation would be limited and allow such very large arrays to be allocated.
If FluxJpegCore can use Stream instead of a byte array and does so effeciently (still a lot of work for you to do there)
Move up to Silverlight 5 and host your app in a 64 bit browser instance.
Going with #AnthonyWJones I'm pretty sure width or height is something like double.NAN. Make sure you place a check to see is width and height is a real number. Also check that your array does not a lot for more than possible within Silverlight

Resources