🔗Asymptote Gallery for Category “Path Orientation” #13
đź”—ccw-fig001

Usage of the algorithm "Simple Polygon Orientation".
Show ccw/fig0010.asy on Github.
Generated with Asymptote 3.00-0.
Categories : Surveys | Path 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 CROISÉ 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);
đź”—ccw-fig002

Show ccw/fig0020.asy on Github.
Generated with Asymptote 3.00-0.
Categories : Surveys | Path Orientation
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);
đź”—ccw-fig003

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.
Show ccw/fig0030.asy on Github.
Generated with Asymptote 3.00-0.
Categories : Surveys | Path Orientation
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);
đź”—ccw-fig004

Show ccw/fig0040.asy on Github.
Generated with Asymptote 3.00-0.
Categories : Surveys | Path Orientation
// 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);