Polygon Tools - Winding Rules

http://www.glprogramming.com/red/chapter11.html

by timknip

HTML

<script src="https://fpcdn.s3.amazonaws.com/apps/polygon-tools/0.4.0/polygon-tools.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/4.5.1/pixi.min.js"></script>
<a href="#" onclick="set1(this)">POLYGON SET 1</a>
<a href="#" onclick="set2(this)">polygon set 2</a>
<a href="#" onclick="set3(this)">polygon set 3</a>
<pre>see http://www.glprogramming.com/red/chapter11.html</pre>
<img src="https://content.screencast.com/users/TimKnip/folders/Jing/media/dfad1aee-5b03-4cb2-bdce-9a4f4ef12234/2017-04-26_1920.png" />
<hr />
<a href="#" onclick="odd(this)">ODD</a>
<a href="#" onclick="nonzero(this)">nonzero</a>
<a href="#" onclick="positive(this)">positive</a>
<a href="#" onclick="negative(this)">negative</a>
<a href="#" onclick="abs_geq_two(this)">abs_geq_two</a>
<hr />

JavaScript

/**
 * The winding rule classifies a region as inside if its winding number 
 * belongs to the chosen category (odd, nonzero, positive, negative, 
 * or "absolute value of greater than or equal to two"). 
 * The odd and nonzero rules are common ways to define the interior. 
 * The positive, negative, and "absolute value>=2" winding rules have 
 * some limited use for polygon CSG (computational solid geometry) operations.
 */
var stage = new PIXI.Container();
var renderer = new PIXI.WebGLRenderer(500, 500);

document.body.appendChild(renderer.view);

const POLY_A = [
	[0, 0],
  [400, 0],
  [400, 400],
  [0, 400]
];

const POLY_B = [
	[100, 100],
  [300, 100],
  [300, 300],
  [100, 300]
];

const POLY_B_REV = [
	[100, 300],
  [300, 300],
  [300, 100],
  [100, 100]
];

const POLY_C = [
	[150, 150],
  [250, 150],
  [250, 250],
  [150, 250]
];

const POLY_C_REV = [
	[150, 250],
  [250, 250],
  [250, 150],
  [150, 150]
];

const POLY_D = [
  [100, 100],
  [300, 100],
  [300, 350],
  [100, 350]
];

const POLY_E = [
  [50, 200],
  [350, 200],
  [350, 250],
  [50, 250]
];

const POLY_F = [
  [200, 400],
  [160, 150],
  [240, 150]
];

let options = {
	polygons: [POLY_A, POLY_B, POLY_C],
  holes: [],
  windingRule: PolygonTools.tesselator.GLU_TESS_WINDING_ODD,
  boundaryOnly: false,
  normal: null,
  autoWinding: false
};

function randomColor () {
  let r = Math.round(Math.random() * 0xff),
      g = Math.round(Math.random() * 0xff),
      b = Math.round(Math.random() * 0xff);
  return r << 16 | g << 8 | b;
}

clearStage = function () {
	for (var i = stage.children.length - 1; i >= 0; i--) {
  	stage.removeChild(stage.children[i]);
  };
  renderer.render(stage);
}

run = function () {
  let result = PolygonTools.tesselator.run(options);
  
  clearStage();
  
  result.forEach(triangles => {
    var paths = triangles.map(triangle => {
        return triangle.reduce((p, pt) => {
          return p.concat(pt.map(p => p));
        }, []);
      });

    var g = new...