Jump to content


dividing a rectangle into a square grid


13 replies to this topic

#1 broli86

    Member

  • Members
  • PipPip
  • 81 posts

Posted 29 April 2008 - 03:12 PM

let's say l and b are the length and breadth of the rectangular plane.

now the plane is represented by four corners:

xmin, ymin
xmax, ymin
xmin, ymax
xmax, ymax


The user is allowed to enter the number of points he wants. Points are going to be spaced from each other at some distance lets say incr. The
rectangular plane is going to be divided into small squares each of
length incr.

unsigned long int numpoints;

So , incr = sqrt((l * b) / numpoints)

I create a point list as:

point3d *point_list = calloc(sizeof(point3d), numpoints);

double xcord, ycord; // represents a random point in the plane.
int i = 0;


for(ycord = ymin; ycord <= ymax; ycord += incr)
{
for(xcord = xmin; xcord<= xmax; xcord+= incr)
{
point_list[i].x = xcord;
point_list[i].y = ycord;
point_list[i].z = 1000;
i++;
}

}

But this approach is giving me a segmentation fault error. Also I checked up and found that when I entered 20,000 as the number of points, it actually created 20164 points causing array to go out of bounds.

#2 yakul

    Member

  • Members
  • PipPip
  • 55 posts

Posted 29 April 2008 - 03:58 PM

I don't know if this is the problem, but notice that the amount of vertices in the grid is larger then the amount of squares in the grid, by l+b-1 in case the square size was exactly 1.
So you need to solve the problem x*incr = l, y*incr = b, x*y*incr^2 = l*b where (x+1)*(y+1) = PointsAmount.

#3 hovermonkey

    Member

  • Members
  • PipPip
  • 38 posts

Posted 29 April 2008 - 04:12 PM

You can't loop on floating point numbers like that and expect to get the right number of loops out. Try this as an example:

float t = 0.0f;

while (t < 1.0f) { printf( "%f\n", t ); t += 0.1f; }

Chances are you'll get 1.0 or 0.999 or something as the last printed number.
The reason is that 0.1 is not exactly representable in floating point, you'll actually get 0.099993 or something slightly different like that. So after adding 0.099993 ten times you are still slightly less than 1.0.

#4 broli86

    Member

  • Members
  • PipPip
  • 81 posts

Posted 29 April 2008 - 04:22 PM

hovermonkey said:

You can't loop on floating point numbers like that and expect to get the right number of loops out. Try this as an example:

float t = 0.0f;

while (t < 1.0f) { printf( "%f\n", t ); t += 0.1f; }

Chances are you'll get 1.0 or 0.999 or something as the last printed number.
The reason is that 0.1 is not exactly representable in floating point, you'll actually get 0.099993 or something slightly different like that. So after adding 0.099993 ten times you are still slightly less than 1.0.

yeah i think this is the problem but the question is how do i resolve it ?

#5 Wernaeh

    Senior Member

  • Members
  • PipPipPipPip
  • 368 posts

Posted 29 April 2008 - 04:23 PM

The point is that you can't just say, create me 20000 points on a rectangle and have them equally spaced. Just consider entering a prime number: like 19. Now, try to distribute these 19 points along a rectangle surface :)

Also, I can't quite figure out what you are doing in your increment calculation.
incr = sqrt((l * b) / numpoints)

Usually, the increment in x should be X / numpointsx and the increment in y should be Y / numpointsy. If you want to enter just an approximate number of points, perhaps do this:
int numpoints;
int numpointsx = sqrt((double)numpoints);
int numpointsy = sqrt((double)numpoints);
numpoints = numpointsx * numpointsy;
which ensures that you have an appropriate number of points for equal spaced tiling.

Cheers,
- Wernaeh
Some call me mathematician, some just call me computer guy. Yet, I prefer the term professional weirdo :)

#6 Wernaeh

    Senior Member

  • Members
  • PipPipPipPip
  • 368 posts

Posted 29 April 2008 - 04:25 PM

The floating point addition is _another_ problem, though.
Since you already have a temporary variable for the running index, why not introduce temps for running coordinates as well and have the loop counters as integers ?
This can easily be integrated with my previously suggested approach where you determine the number of points both in x and y direction.

Cheers,
- Wernaeh
Some call me mathematician, some just call me computer guy. Yet, I prefer the term professional weirdo :)

#7 broli86

    Member

  • Members
  • PipPip
  • 81 posts

Posted 29 April 2008 - 04:30 PM

Wernaeh said:

The floating point addition is _another_ problem, though.
Since you already have a temporary variable for the running index, why not introduce temps for running coordinates as well and have the loop counters as integers ?
This can easily be integrated with my previously suggested approach where you determine the number of points both in x and y direction.

Cheers,
- Wernaeh

agreed but the problem is i do need extremely huge number of points on a small plane( eg: l = b = 20)which i cannot do with integer incrementations.

#8 Wernaeh

    Senior Member

  • Members
  • PipPipPipPip
  • 368 posts

Posted 29 April 2008 - 04:33 PM

float xsize = xlength / numpointsx;
float ysize = ylength / numpointsy;

for (int yi = 0; yi < numpointsy; ++yi)
{
     for (int xi = 0; xi < numpointsx; ++xi)
     {
          pointinarray[i].x = xi * xsize;
          pointinarray[i].y = yi * ysize;
          ++i;
     }
}

Some call me mathematician, some just call me computer guy. Yet, I prefer the term professional weirdo :)

#9 broli86

    Member

  • Members
  • PipPip
  • 81 posts

Posted 29 April 2008 - 04:44 PM

Wernaeh said:


float xsize = xlength / numpointsx;

float ysize = ylength / numpointsy;


for (int yi = 0; yi < numpointsy; ++yi)

{

     for (int xi = 0; xi < numpointsx; ++xi)

     {

          pointinarray[i].x = xi * xsize;

          pointinarray[i].y = yi * ysize;

          ++i;

     }

}



thanks, I'm getting your approach but shouldn't this be:


float xsize = xlength / numpointsx;

float ysize = ylength / numpointsy;


for (int yi = 0; yi < numpointsy; ++yi)

{

     for (int xi = 0; xi < numpointsx; ++xi)

     {

          pointinarray[i].x = xmin + xi * xsize;

          pointinarray[i].y = ymin + yi * ysize;

          ++i;

     }

}


What I would do is I will check the values of x and y for last entry in pointinarray[i] and compare it with xmax and ymax.

#10 Wernaeh

    Senior Member

  • Members
  • PipPipPipPip
  • 368 posts

Posted 29 April 2008 - 04:46 PM

Yup, the xmin/ymin were left out and not really required for the basic idea.

The boundary check you mentioned can be omitted if you allocate enough space for numpointsy * numpointsx points :)

Cheers,
- Wernaeh
Some call me mathematician, some just call me computer guy. Yet, I prefer the term professional weirdo :)

#11 broli86

    Member

  • Members
  • PipPip
  • 81 posts

Posted 29 April 2008 - 04:59 PM

Wernaeh said:

Yup, the xmin/ymin were left out and not really required for the basic idea.

The boundary check you mentioned can be omitted if you allocate enough space for numpointsy * numpointsx points :)

Cheers,
- Wernaeh


I just checked :

xmin = ymin = -10
xmax = ymax = 10

numpoints = 14000

actual numpoints (after numpointsx * numpointsy calculation) : 13924

xmax : 9.83509
ymax: 9.83509



#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int main(void)
{
	long int numpoints;
	printf("Enter num of points\n");
	scanf("%d", &numpoints);
        long int numpointsx = sqrt((double)numpoints);
        long int numpointsy = sqrt((double)numpoints);
        numpoints = numpointsx * numpointsy;
        int i =  0;
	typedef struct point
       {
		float x, y;

       } point;
	point *pointinarray;

	pointinarray = calloc(sizeof(point), numpoints);
	float xlength, ylength;
	xlength = ylength = 20;
	float xmin, ymin;
        xmin = ymin  = -10;
	float xmax, ymax;
	xmax = ymax  = 10;
        float xsize = xlength / numpointsx;
        float ysize = ylength / numpointsy;

	for (int yi = 0; yi < numpointsy; ++yi)
       {
            for (int xi = 0; xi < numpointsx; ++xi)
           {
                pointinarray[i].x = xmin + xi * xsize;
                pointinarray[i].y = ymin + yi * ysize;
                ++i;
           }
      }

      printf("i: %d xmax: %f ymax: %f\n",i, pointinarray[i-1].x, pointinarray[i-1].y);
      return 0;

}



#12 Wernaeh

    Senior Member

  • Members
  • PipPipPipPip
  • 368 posts

Posted 29 April 2008 - 05:10 PM

Jup, there's still some "correction" required if you need to hit the edges:
In this case you need to generate an "extra point" into each direction, i.e. have
        float xsize = xlength / (numpointsx - 1);
        float ysize = ylength / (numpointsy - 1);
and then use <= in both loops.

This comes from the fact that the xsize, ysize you calculate are the size of the polys among the points, and if you think about it, you'll notice that there is always one point more in each direction than polygons.

Cheers,
- Wernaeh
Some call me mathematician, some just call me computer guy. Yet, I prefer the term professional weirdo :)

#13 broli86

    Member

  • Members
  • PipPip
  • 81 posts

Posted 29 April 2008 - 05:29 PM

Wernaeh said:

Jup, there's still some "correction" required if you need to hit the edges:
In this case you need to generate an "extra point" into each direction, i.e. have

        float xsize = xlength / (numpointsx - 1);

        float ysize = ylength / (numpointsy - 1);

and then use <= in both loops.

This comes from the fact that the xsize, ysize you calculate are the size of the polys among the points, and if you think about it, you'll notice that there is always one point more in each direction than polygons.

Cheers,
- Wernaeh

With this approach, now i have extra points:

For eg. numpoints = 14000 //entered by user

actual numpoints = 14161

xmax = 10.170940
ymax = same as above

but i don't mind really :)

what i will do is that i am doing actual calculations, i will simply not consider points where:

x > xmax || y > ymax

x or y cannot be less than xmin, ymin anyway :)

#14 z80

    Valued Member

  • Members
  • PipPipPip
  • 104 posts

Posted 29 April 2008 - 08:46 PM

broli86 said:

i will simply not consider points where:

x > xmax || y > ymax

Terrible solution IMHO.. get your math and logic right instead...





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users