|
|
|
Figure 0001: fig0010.asy (Compiled with Asymptote version 1.84svn-r4619) |
/*
About the used algorithms look at:
http://cgafaq.info/wiki/Simple_Polygon_Orientation
*/
size(8cm, false);
real signedArea(pair [] pt)
{
// Return the signed area of a simple (NON CROSSED) polygon of vertex "pt"
// Retourne l'aire algébrique d'un polygone NON CROIÉ
pair [] pt_= copy(pt);
real n=pt.length,
sa=0;
pt_.push(pt_[0]);
pt_.push(pt_[1]);
for (int i=1; i<=n; ++i) sa +=pt_[i].x * (pt_[i+1].y - pt_[i-1].y);
return sa/2;
}
bool counterclockwise(pair [] pt)
{
// Return "true" if the polygon (SIMPLE CURVE i.e. NON CROSSED)
// of vertex "pt" is counterclockwise
// Retourne "true" si le polygone (NON CROISÉ) de sommets "pt"
// est dans le sens des aiguilles d'une montre
return (signedArea(pt) > 0);
}
pair [] reverse(pair [] pt)
{
pair [] pt_=copy(pt);
int begin=0, end=pt.length-1;
while (begin<end)
{
pair temp=pt_[begin];
pt_[begin]=pt_[end];
pt_[end]=temp;
++begin; --end;
}
return pt_;
}
pair [] counterclockdirected(pair [] pt)
{
if (counterclockwise(pt)) return pt; else return reverse(pt);
}
path polygon(pair [] pt)
{
int l=pt.length;
guide opath;
for (int i=0; i<l; ++i)
{
opath = opath--pt[i];
}
return opath;
}
pair [] pg = {(0,0), (1,0), (1,1), (2,2), (-1,1)};
draw(polygon(pg)--cycle,
Arrow(Relative(.1)), BeginBar);
draw(polygon(counterclockdirected(reverse(pg)))--cycle,
Arrow(position=Relative(.2), FillDraw(red)), BeginBar);
|
|
|
Figure 0002: fig0020.asy (Compiled with Asymptote version 1.84svn-r4619) |
size(6cm);
bool counterclockwise(path g, int n=10^3)
{
// Return "true" if "g" (SIMPLE CURVE i.e. NON CROSSED) is counterclockwise
// Retounre "true" si "g" (NON CROISÉ) est dans le sens contraire des aiguilles d'une montre
if (!cyclic(g) || length(g)==0) abort("The function 'clocksize' needs cyclic path.");
pair [] pt;
real l=length(g),
step=1/n,
t=0,
sa=0;
do {
sa +=point(g,t).x * (point(g,t+step).y - point(g,t-step).y);
t+=step;
} while (t<l);
return (sgn(sa) > 0);
}
path counterclockdirected(path g,int n=10^3)
{
// Return "g" (SIMPLE CURVE i.e. NON CROSSED) counterclockwise
// Retourne "g" (NON CROISÉ) dans le sens des aiguilles d'une montre
if (counterclockwise(g,n)) return g; else return reverse(g);
}
path p=unitcircle;
draw(counterclockdirected(reverse(p)),
Arrow(Relative(.1)), BeginBar);
draw(counterclockdirected(p),
Arrow(position=Relative(.2),FillDraw(red)), BeginBar);
|
|
|
Figure 0003: fig0030.asy (Compiled with Asymptote version 1.84svn-r4619) |
// Use of the native windingnumber Asymptote routine
// this is the most fast and robust.
// Utilisation du nombre d'enroulement avec la routine native windingnumber d'Asymptote
// c'est plus rapide et plus robuste.
/*
Explanations are here: http://mathworld.wolfram.com/ContourWindingNumber.html
*/
size(6cm,0, false);
bool counterclockwise(path g, pair z) {return windingnumber(g,z) > 0;}
path counterclockdirected(path g,pair z)
{
if (counterclockwise(g,z)) return g; else return reverse(g);
}
pair z=(1,0);
dot(z);
path p=(0,0){N}..(4,0){N}..cycle;
draw(counterclockdirected(reverse(p),z),Arrow(Relative(.1)), BeginBar);
draw(counterclockdirected(p,z),Arrow(position=Relative(.2),FillDraw(red)), BeginBar);
pair z=(3,-2);
dot(z);
path p=(4,-2){N}..(0,-2){N}..cycle;
draw(counterclockdirected(reverse(p),z),Arrow(Relative(.1)), BeginBar);
draw(counterclockdirected(p,z),Arrow(position=Relative(.2),FillDraw(red)), BeginBar);
pair z=(1,-4.5);
dot(z);
path p=yscale(.75)*((0,-6){N}..(2,-6){S}..(0,-6){N}..(4,-6){S}..cycle);
draw(counterclockdirected(reverse(p),z),Arrow(Relative(.1)), BeginBar);
draw(counterclockdirected(p,z),Arrow(position=Relative(.2),FillDraw(red)), BeginBar);
pair z=(3,-8);
dot(z);
path p=shift((0,-3.5))*p;
draw(counterclockdirected(reverse(p),z),Arrow(Relative(.1)), BeginBar);
draw(counterclockdirected(p,z),Arrow(position=Relative(.2),FillDraw(red)), BeginBar);
|
|
|
Figure 0004: fig0040.asy (Compiled with Asymptote version 1.84svn-r4619) |
// Use of the windingnumber works also for CROSSED curves
size(8cm,10cm,false);
import math;
bool counterclockwise(path g)
{
// Return "true" if "g" is counterclockwise
// Retounre "true" si "g" est dans le sens contraire des aiguilles d'une montre
return (windingnumber(g,inside(g)) > 0);
}
path counterclockdirected(path g)
{
if (counterclockwise(g)) return g; else return reverse(g);
}
guide p=randompath(30)..cycle;
draw(counterclockdirected(reverse(p)),Arrow(10bp,Relative(0.025)), BeginBar);
draw(counterclockdirected(p),Arrow(10bp,FillDraw(red),Relative(.05)), BeginBar);
Dernière modification/Last modified: Sun Sep 20 18:47:45 CEST 2009
Philippe Ivaldi