Computing Radials inside a Polygon

5 messages Options
Embed this post
Permalink
Jo-4

Computing Radials inside a Polygon

Reply Threaded More More options
Print post
Permalink
First of all, I apologize to post this question when my code is not
using GEOS but I think this is a generic geometry problem so it really
does not matter which API, I am using (I'm using OGR).
I need to compute a certain number of equally spaced radials inside a
polygon, given that each segment should start on the centroide and end
somewhere in its boundary (or external ring).
The algorithm I designed, follows this steps:
- given a certain number of radials(n), calculate the angle(fangle)
that equally divides the circle in n/2 sectors;
- fetch a point from the perimeter of the minimum enclosing circle (to
guarantee the point is outside the perimeter);
- loop n times, rotating this point around using fangle for this
rotation; at each step, the rotated vector will be a vector that links
the centroide to the rotated point; to get a vector inside the
polygon, this vector is intersected with the polygon and we use the
resulting geometry.

I am getting a strange (wrong) result, so I guess I am not seeing
things right (or there is a bug in my code :-)) because I get equally
spaced radials covering approximately a quarter if the polygon, and
the angle from the first point to the first rotated point does not
seem correct... image here:

http://ladybug.no-ip.org/files/radials.png


Here is my code! I would be very grateful for any suggestions that
could point me in the right direction... also, if you have any ideas
of computing this using GEOS I would not mind to go for them;
                               thanks in advance,
                                                           cheers, Jo

        OGRPoint centroide;
        if (Centroid(¢roide)!=OGRERR_NONE) return false; // get centroid of polygon
        const OGRLinearRing * pRing=minCircle.getExteriorRing(); //get
external ring of the minimum enclosing circle

        if (pRing->getNumPoints()<1) {printf("Ring not valid!\n");return false;}
        OGRPoint startPt;
        pRing->getPoint(0, &startPt);//get one point in the minimum enclosing
circle external ring

        OGRLineString aLine;
        aLine.addPoint(¢roide);
        aLine.addPoint(&startPt);
        aLine.addPoint(¢roide);

        if (!aLine.IsValid()) {printf("Line is not valid!\n");return false;}

        OGRGeometry* ints=Intersection(&aLine);
        radials.addGeometry(ints);

        double ns=n/0.5; //n is the number of radials
        double fangle=PI/(ns*0.5);// assumed that the whole circumference is
2 PI radians

        for (size_t i=0; i < n; ++i){

                OGRLineString dLine;
                dLine.addPoint(¢roide);

                double rx=startPt.getX()*cos(fangle)-startPt.getY()*sin(fangle);
//rotated x- is this correct?
                double ry=startPt.getX()*sin(fangle)+startPt.getY()*cos(fangle);
//rotated y- is this correct?

                startPt.setX(rx);
                startPt.setY(ry);
                dLine.addPoint(&startPt);
                dLine.addPoint(¢roide);

                OGRGeometry* ints=Intersection(&dLine);
                radials.addGeometry(ints);

        }
_______________________________________________
geos-devel mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/geos-devel
sanak

Re: Computing Radials inside a Polygon

Reply Threaded More More options
Print post
Permalink
Hi Jo,

I think that each rotate angles should be calculated more simply.
(I think rotation matrix is valid when centroid is equal to origine(0, 0).)

The following code is pseudo code. (Sorry I haven't OGR environment...)

===================================
// get minCircle radius. (If radius is not calculated yet)
double radius=Distance(&centroid, &startPt); // I don't know that Distance function is implemented in OGR...
// get start angle.
double startAngle=atan2(&startPt.getY()-&centroid.getY(), &startPt.getX()-&centroid.getX());

for (size_t i=0; i <n; ++i){
        OGRLineString dLine;
        dLine.addPoint(&centroid);

        double rx=centroid.getX() + radius*cos(startAngle+fangle*i);
        double ry=centroid.getY() + radius*sin(startAngle+fangle*i);
         :
}
===================================

Regards,

Sanak.

2009/8/24 Jo <[hidden email]>
First of all, I apologize to post this question when my code is not
using GEOS but I think this is a generic geometry problem so it really
does not matter which API, I am using (I'm using OGR).
I need to compute a certain number of equally spaced radials inside a
polygon, given that each segment should start on the centroide and end
somewhere in its boundary (or external ring).
The algorithm I designed, follows this steps:
- given a certain number of radials(n), calculate the angle(fangle)
that equally divides the circle in n/2 sectors;
- fetch a point from the perimeter of the minimum enclosing circle (to
guarantee the point is outside the perimeter);
- loop n times, rotating this point around using fangle for this
rotation; at each step, the rotated vector will be a vector that links
the centroide to the rotated point; to get a vector inside the
polygon, this vector is intersected with the polygon and we use the
resulting geometry.

I am getting a strange (wrong) result, so I guess I am not seeing
things right (or there is a bug in my code :-)) because I get equally
spaced radials covering approximately a quarter if the polygon, and
the angle from the first point to the first rotated point does not
seem correct... image here:

http://ladybug.no-ip.org/files/radials.png


Here is my code! I would be very grateful for any suggestions that
could point me in the right direction... also, if you have any ideas
of computing this using GEOS I would not mind to go for them;
                              thanks in advance,
                                                          cheers, Jo

       OGRPoint centroide;
       if (Centroid(&centroide)!=OGRERR_NONE) return false; // get centroid of polygon
       const OGRLinearRing * pRing=minCircle.getExteriorRing(); //get
external ring of the minimum enclosing circle

       if (pRing->getNumPoints()<1) {printf("Ring not valid!\n");return false;}
       OGRPoint startPt;
       pRing->getPoint(0, &startPt);//get one point in the minimum enclosing
circle external ring

       OGRLineString aLine;
       aLine.addPoint(&centroide);
       aLine.addPoint(&startPt);
       aLine.addPoint(&centroide);

       if (!aLine.IsValid()) {printf("Line is not valid!\n");return false;}

       OGRGeometry* ints=Intersection(&aLine);
       radials.addGeometry(ints);

       double ns=n/0.5; //n is the number of radials
       double fangle=PI/(ns*0.5);// assumed that the whole circumference is
2 PI radians

       for (size_t i=0; i < n; ++i){

               OGRLineString dLine;
               dLine.addPoint(&centroide);

               double rx=startPt.getX()*cos(fangle)-startPt.getY()*sin(fangle);
//rotated x- is this correct?
               double ry=startPt.getX()*sin(fangle)+startPt.getY()*cos(fangle);
//rotated y- is this correct?

               startPt.setX(rx);
               startPt.setY(ry);
               dLine.addPoint(&startPt);
               dLine.addPoint(&centroide);

               OGRGeometry* ints=Intersection(&dLine);
               radials.addGeometry(ints);

       }
_______________________________________________
geos-devel mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/geos-devel


_______________________________________________
geos-devel mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/geos-devel
Jo-4

Re: Computing Radials inside a Polygon

Reply Threaded More More options
Print post
Permalink
In reply to this post by Jo-4
Hi Jo,

I think that each rotate angles should be calculated more simply.
(I think rotation matrix is valid when centroid is equal to origine(0, 0).)

The following code is pseudo code. (Sorry I haven't OGR environment...)

===================================
// get minCircle radius. (If radius is not calculated yet)
double radius=Distance(¢roid, &startPt); // I don't know that Distance
function is implemented in OGR...
// get start angle.
double startAngle=atan2(&startPt.getY()-¢roid.getY(),
&startPt.getX()-¢roid.getX());

for (size_t i=0; i <n; ++i){
       OGRLineString dLine;
       dLine.addPoint(¢roid);

       double rx=centroid.getX() + radius*cos(startAngle+fangle*i);
       double ry=centroid.getY() + radius*sin(startAngle+fangle*i);
        :
}
===================================

Regards,

Sanak.

Hi Sanak,
First of all, thanks for your reply!
I think I didn't explain myself clearly though...

The idea is to compute radials from the centroid of the polygon, to
its external ring, at equal intervals. Something like this:

http://ladybug.no-ip.org/files/radials_final.png

I had the idea of starting with a vector that starts in the centroid
and ends up in the external ring (at any point), and therefore its
length equals the radius; to make things simple I choose a point that
is in the same x-alignment as the centroid, and so the start angle in
your code would be null. My start vector is something like this:

http://ladybug.no-ip.org/files/start.png

Than my idea, was to rotate this vector around the centroid, at a
constant angle, and get the radials.
Lets assume for simplicity that the angle is 90 degrees (PI/2 radians)
and therefore I want to end up with four radials.
As I compute the new locations of the rotated endpoint of the vector,
I store this point on a stl container, so that in the end I can loop
through all these locations and generate my vectors.
Here is a GEOS version of my code:

        //////////GEOS VERSION /////
        std::vector<geos::geom::Point*> pts;

        geos::geom::GeometryFactory factory;
        geos::geom::Coordinate coordC(ogrCentroid.getX(),ogrCentroid.getY());

        //create centroid from given point
        geos::geom::Point* centroid = factory.createPoint(coordC);

        //create start pt as any point on the perimeter (for instance, a
point aligned in x with the centroid)
        geos::geom::Coordinate coordS(ogrCentroid.getX()+radius,ogrCentroid.getY());
        geos::geom::Point* startPt = factory.createPoint(coordS);

        pts.push_back(startPt);

        //nr radials=4; angle=90 deg= PI/2
        double fangle=PI/2.0;

        for (size_t i=0; i <4; ++i){

                double x=pts.back()->getX();
                double y=pts.back()->getY();

                double rx=x*cos(fangle)-y*sin(fangle);
                double ry=x*sin(fangle)+y*cos(fangle);

                geos::geom::Coordinate coords(x+rx,y+ry);
                geos::geom::Point* aPoint = factory.createPoint(coords);
       
                pts.push_back(aPoint);
        }

Let me mention that this code is *not* doing what I want, since:
- I am getting the wrong angle between the start point and the first
iteration point;
- the angles do not appear to be 90 degrees;
- I think also the angles are not constant;

Here is a screenshot of my output:

http://ladybug.no-ip.org/files/output.png

So I guess there must be some assumption (or more than one, actually)
that is wrong in my code :-)
Again, I would be very grateful for any observations or suggestions...
thanks in advance for your help!

                                       cheers,
                                                     Jo
_______________________________________________
geos-devel mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/geos-devel
Jo-4

Re: Computing Radials inside a Polygon

Reply Threaded More More options
Print post
Permalink
In reply to this post by Jo-4
Thinking better, I could see what I was doing wrong.
I was rotating a point around (0,0), rather than rotating it around my
origin (the centroid). Therefore, I had to add the difference between
the point and centroid coordinates to the sin and cosine terms:
       
                double rx=centroid->getX()+cos(fangle)*(x-centroid->getX())-sin(fangle)*(y-centroid->getY());
                double ry=centroid->getY()+sin(fangle)*(x-centroid->getX())+cos(fangle)*(y-centroid->getY());

And calling consecutively this function, gives me the equally spaced
radials from a centroid of a polygon to its external ring; in this
example, using a 45 degrees angle:

http://ladybug.no-ip.org/files/radials_calc.png

                                   cheers,
                                              Jo


2009/8/29  <[hidden email]>:

> Send geos-devel mailing list submissions to
>        [hidden email]
>
> To subscribe or unsubscribe via the World Wide Web, visit
>        http://lists.osgeo.org/mailman/listinfo/geos-devel
> or, via email, send a message with subject or body 'help' to
>        [hidden email]
>
> You can reach the person managing the list at
>        [hidden email]
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of geos-devel digest..."
>
>
> Today's Topics:
>
>   1. Re: Computing Radials inside a Polygon (Jo)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Sat, 29 Aug 2009 16:16:23 +0100
> From: Jo <[hidden email]>
> Subject: [geos-devel] Re: Computing Radials inside a Polygon
> To: [hidden email]
> Message-ID:
>        <[hidden email]>
> Content-Type: text/plain; charset=ISO-8859-1
>
> Hi Jo,
>
> I think that each rotate angles should be calculated more simply.
> (I think rotation matrix is valid when centroid is equal to origine(0, 0).)
>
> The following code is pseudo code. (Sorry I haven't OGR environment...)
>
> ===================================
> // get minCircle radius. (If radius is not calculated yet)
> double radius=Distance(¢roid, &startPt); // I don't know that Distance
> function is implemented in OGR...
> // get start angle.
> double startAngle=atan2(&startPt.getY()-¢roid.getY(),
> &startPt.getX()-¢roid.getX());
>
> for (size_t i=0; i <n; ++i){
>       OGRLineString dLine;
>       dLine.addPoint(¢roid);
>
>       double rx=centroid.getX() + radius*cos(startAngle+fangle*i);
>       double ry=centroid.getY() + radius*sin(startAngle+fangle*i);
>        :
> }
> ===================================
>
> Regards,
>
> Sanak.
>
> Hi Sanak,
> First of all, thanks for your reply!
> I think I didn't explain myself clearly though...
>
> The idea is to compute radials from the centroid of the polygon, to
> its external ring, at equal intervals. Something like this:
>
> http://ladybug.no-ip.org/files/radials_final.png
>
> I had the idea of starting with a vector that starts in the centroid
> and ends up in the external ring (at any point), and therefore its
> length equals the radius; to make things simple I choose a point that
> is in the same x-alignment as the centroid, and so the start angle in
> your code would be null. My start vector is something like this:
>
> http://ladybug.no-ip.org/files/start.png
>
> Than my idea, was to rotate this vector around the centroid, at a
> constant angle, and get the radials.
> Lets assume for simplicity that the angle is 90 degrees (PI/2 radians)
> and therefore I want to end up with four radials.
> As I compute the new locations of the rotated endpoint of the vector,
> I store this point on a stl container, so that in the end I can loop
> through all these locations and generate my vectors.
> Here is a GEOS version of my code:
>
>        //////////GEOS VERSION /////
>        std::vector<geos::geom::Point*> pts;
>
>        geos::geom::GeometryFactory factory;
>        geos::geom::Coordinate coordC(ogrCentroid.getX(),ogrCentroid.getY());
>
>        //create centroid from given point
>        geos::geom::Point* centroid = factory.createPoint(coordC);
>
>        //create start pt as any point on the perimeter (for instance, a
> point aligned in x with the centroid)
>        geos::geom::Coordinate coordS(ogrCentroid.getX()+radius,ogrCentroid.getY());
>        geos::geom::Point* startPt = factory.createPoint(coordS);
>
>        pts.push_back(startPt);
>
>        //nr radials=4; angle=90 deg= PI/2
>        double fangle=PI/2.0;
>
>        for (size_t i=0; i <4; ++i){
>
>                double x=pts.back()->getX();
>                double y=pts.back()->getY();
>
>                double rx=x*cos(fangle)-y*sin(fangle);
>                double ry=x*sin(fangle)+y*cos(fangle);
>
>                geos::geom::Coordinate coords(x+rx,y+ry);
>                geos::geom::Point* aPoint = factory.createPoint(coords);
>
>                pts.push_back(aPoint);
>        }
>
> Let me mention that this code is *not* doing what I want, since:
> - I am getting the wrong angle between the start point and the first
> iteration point;
> - the angles do not appear to be 90 degrees;
> - I think also the angles are not constant;
>
> Here is a screenshot of my output:
>
> http://ladybug.no-ip.org/files/output.png
>
> So I guess there must be some assumption (or more than one, actually)
> that is wrong in my code :-)
> Again, I would be very grateful for any observations or suggestions...
> thanks in advance for your help!
>
>                                       cheers,
>                                                     Jo
>
>
> ------------------------------
>
> _______________________________________________
> geos-devel mailing list
> [hidden email]
> http://lists.osgeo.org/mailman/listinfo/geos-devel
>
> End of geos-devel Digest, Vol 82, Issue 25
> ******************************************
>



--
"#define QUESTION ((bb) || !(bb))"  (Shakespeare)
_______________________________________________
geos-devel mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/geos-devel
sanak

Re: Re: Computing Radials inside a Polygon

Reply Threaded More More options
Print post
Permalink
Hi Jo,

Thanks for your reply.

Ok, your last image seems to be no problem.

Regards,

Sanak.

2009/8/30 Jo <[hidden email]>
Thinking better, I could see what I was doing wrong.
I was rotating a point around (0,0), rather than rotating it around my
origin (the centroid). Therefore, I had to add the difference between
the point and centroid coordinates to the sin and cosine terms:

               double rx=centroid->getX()+cos(fangle)*(x-centroid->getX())-sin(fangle)*(y-centroid->getY());
               double ry=centroid->getY()+sin(fangle)*(x-centroid->getX())+cos(fangle)*(y-centroid->getY());

And calling consecutively this function, gives me the equally spaced
radials from a centroid of a polygon to its external ring; in this
example, using a 45 degrees angle:

http://ladybug.no-ip.org/files/radials_calc.png

                                  cheers,
                                             Jo


2009/8/29  <[hidden email]>:
> Send geos-devel mailing list submissions to
>        [hidden email]
>
> To subscribe or unsubscribe via the World Wide Web, visit
> or, via email, send a message with subject or body 'help' to
>        [hidden email]
>
> You can reach the person managing the list at
>        [hidden email]
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of geos-devel digest..."
>
>
> Today's Topics:
>
>   1. Re: Computing Radials inside a Polygon (Jo)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Sat, 29 Aug 2009 16:16:23 +0100
> From: Jo <[hidden email]>
> Subject: [geos-devel] Re: Computing Radials inside a Polygon
> To: [hidden email]
> Message-ID:
>        <[hidden email]>
> Content-Type: text/plain; charset=ISO-8859-1
>
> Hi Jo,
>
> I think that each rotate angles should be calculated more simply.
> (I think rotation matrix is valid when centroid is equal to origine(0, 0).)
>
> The following code is pseudo code. (Sorry I haven't OGR environment...)
>
> ===================================
> // get minCircle radius. (If radius is not calculated yet)
> double radius=Distance(&centroid, &startPt); // I don't know that Distance
> function is implemented in OGR...
> // get start angle.
> double startAngle=atan2(&startPt.getY()-&centroid.getY(),
> &startPt.getX()-&centroid.getX());
>
> for (size_t i=0; i <n; ++i){
>       OGRLineString dLine;
>       dLine.addPoint(&centroid);
>
>       double rx=centroid.getX() + radius*cos(startAngle+fangle*i);
>       double ry=centroid.getY() + radius*sin(startAngle+fangle*i);
>        :
> }
> ===================================
>
> Regards,
>
> Sanak.
>
> Hi Sanak,
> First of all, thanks for your reply!
> I think I didn't explain myself clearly though...
>
> The idea is to compute radials from the centroid of the polygon, to
> its external ring, at equal intervals. Something like this:
>
> http://ladybug.no-ip.org/files/radials_final.png
>
> I had the idea of starting with a vector that starts in the centroid
> and ends up in the external ring (at any point), and therefore its
> length equals the radius; to make things simple I choose a point that
> is in the same x-alignment as the centroid, and so the start angle in
> your code would be null. My start vector is something like this:
>
> http://ladybug.no-ip.org/files/start.png
>
> Than my idea, was to rotate this vector around the centroid, at a
> constant angle, and get the radials.
> Lets assume for simplicity that the angle is 90 degrees (PI/2 radians)
> and therefore I want to end up with four radials.
> As I compute the new locations of the rotated endpoint of the vector,
> I store this point on a stl container, so that in the end I can loop
> through all these locations and generate my vectors.
> Here is a GEOS version of my code:
>
>        //////////GEOS VERSION /////
>        std::vector<geos::geom::Point*> pts;
>
>        geos::geom::GeometryFactory factory;
>        geos::geom::Coordinate coordC(ogrCentroid.getX(),ogrCentroid.getY());
>
>        //create centroid from given point
>        geos::geom::Point* centroid = factory.createPoint(coordC);
>
>        //create start pt as any point on the perimeter (for instance, a
> point aligned in x with the centroid)
>        geos::geom::Coordinate coordS(ogrCentroid.getX()+radius,ogrCentroid.getY());
>        geos::geom::Point* startPt = factory.createPoint(coordS);
>
>        pts.push_back(startPt);
>
>        //nr radials=4; angle=90 deg= PI/2
>        double fangle=PI/2.0;
>
>        for (size_t i=0; i <4; ++i){
>
>                double x=pts.back()->getX();
>                double y=pts.back()->getY();
>
>                double rx=x*cos(fangle)-y*sin(fangle);
>                double ry=x*sin(fangle)+y*cos(fangle);
>
>                geos::geom::Coordinate coords(x+rx,y+ry);
>                geos::geom::Point* aPoint = factory.createPoint(coords);
>
>                pts.push_back(aPoint);
>        }
>
> Let me mention that this code is *not* doing what I want, since:
> - I am getting the wrong angle between the start point and the first
> iteration point;
> - the angles do not appear to be 90 degrees;
> - I think also the angles are not constant;
>
> Here is a screenshot of my output:
>
> http://ladybug.no-ip.org/files/output.png
>
> So I guess there must be some assumption (or more than one, actually)
> that is wrong in my code :-)
> Again, I would be very grateful for any observations or suggestions...
> thanks in advance for your help!
>
>                                       cheers,
>                                                     Jo
>
>
> ------------------------------
>
> _______________________________________________
> geos-devel mailing list
> [hidden email]
> http://lists.osgeo.org/mailman/listinfo/geos-devel
>
> End of geos-devel Digest, Vol 82, Issue 25
> ******************************************
>



--
"#define QUESTION ((bb) || !(bb))"  (Shakespeare)
_______________________________________________
geos-devel mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/geos-devel


_______________________________________________
geos-devel mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/geos-devel