Le sens des aiguilles d'une montre
Clockwise
List of pictures
Figure 0001
figure 0001
Figure 0002
figure 0002
Figure 0003
figure 0003
Figure 0004
figure 0004
Figure 0005
figure 0005
Figure 0001: fig0010.asy
Figure 0001
/*
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
Figure 0002
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
Figure 0003
/*
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
Figure 0004
// Use of the windingnumber for simple curves (NON CROSSED)
// The most fast and robust with Asymptote.
// Utilisation du nombre d'enroulement pour des courbes NON CROISÉES
// Le plus rapide et robuste avec Asymptote.

size(6cm,0, false);
import math;
import roundedpath;

bool counterclockwise(path g)
{
  // 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  
  return windingnumber(g,inside(g)) > 0;
}

path counterclockdirected(path g)
{
  if (counterclockwise(g)) return g; else return reverse(g);
}

path p = (0,1)..(.8,1)..(.8,.6)..(.4,.6)..(.4,.2)..(.8,.2)..(.8,-.2)..(.4,-.2)..(.4,-.6)..(.8,-.6)..(.8,-1)..(0,-1)..cycle;

draw(counterclockdirected(reverse(p)),
     Arrow(Relative(.1)), BeginBar);
draw(counterclockdirected(p),
     Arrow(position=Relative(.2),FillDraw(red)), BeginBar);
Figure 0005: fig0050.asy
Figure 0005
size(8cm,10cm,false);

import math;

bool counterclockwise(path g)
{
  // 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  
  return (windingnumber(g,inside(g)) > 0);
}

path counterclockdirected(path g)
{
  if (counterclockwise(g)) return g; else return reverse(g);
}

guide randompath(int pt, real u=1)
{
  guide rpath;
  pair ptl;
  for(int i=1; i<=pt; ++i) {
    pair ptt=ptl+u*(rand()/randMax-0.5,rand()/randMax-0.5);
    rpath=rpath..ptt;
    ptl=ptt;
  }
  return rpath;
}

guide p=randompath(50,4)..cycle;
draw(counterclockdirected(reverse(p)),Arrow(Relative(0.005)), BeginBar);
draw(counterclockdirected(p),Arrow(position=Relative(.005),FillDraw(red)), BeginBar);
label("Attention - Caution",(xpart(.5(max(p)+min(p))),ypart(min(p))));

Dernière modification/Last modified: lun avr 2 13:26:07 CEST 2007
Philippe Ivaldi

Valide XHTML