flatten-js
Version:
Javascript library for 2d geometry
579 lines (501 loc) • 44.1 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>classes/face.js - Documentation</title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
<div class="navicon"></div>
</label>
<label for="nav-trigger" class="overlay"></label>
<nav>
<li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Arc.html">Arc</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#breakToFunctional">breakToFunctional</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#chordHeight">chordHeight</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#clone">clone</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#contains">contains</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#distanceTo">distanceTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#intersect">intersect</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#middle">middle</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#reverse">reverse</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#rotate">rotate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#split">split</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#svg">svg</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#tangentInEnd">tangentInEnd</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#tangentInStart">tangentInStart</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#toJSON">toJSON</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#transform">transform</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Arc.html#translate">translate</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Box.html">Box</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Box.html#clone">clone</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Box.html#equal_to">equal_to</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Box.html#intersect">intersect</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Box.html#less_than">less_than</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Box.html#merge">merge</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Box.html#not_intersect">not_intersect</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Box.html#set">set</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Box.html#svg">svg</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Circle.html">Circle</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Circle.html#clone">clone</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Circle.html#contains">contains</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Circle.html#distanceTo">distanceTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Circle.html#intersect">intersect</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Circle.html#svg">svg</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Circle.html#toArc">toArc</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Circle.html#toJSON">toJSON</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Edge.html">Edge</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Edge.html#contains">contains</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Edge.html#middle">middle</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Edge.html#setInclusion">setInclusion</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Edge.html#setOverlap">setOverlap</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Face.html">Face</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Face.html#append">append</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Face.html#area">area</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Face.html#insert">insert</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Face.html#isEmpty">isEmpty</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Face.html#isSimple">isSimple</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Face.html#orientation">orientation</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Face.html#remove">remove</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Face.html#reverse">reverse</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Face.html#setArcLength">setArcLength</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Face.html#signedArea">signedArea</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Face.html#svg">svg</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Image.html">Image</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Line.html">Line</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Line.html#clone">clone</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Line.html#contains">contains</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Line.html#distanceTo">distanceTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Line.html#incidentTo">incidentTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Line.html#intersect">intersect</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Line.html#parallelTo">parallelTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Line.html#svg">svg</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Line.html#toJSON">toJSON</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Matrix.html">Matrix</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Matrix.html#clone">clone</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Matrix.html#equalTo">equalTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Matrix.html#multiply">multiply</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Matrix.html#rotate">rotate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Matrix.html#scale">scale</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Matrix.html#transform">transform</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Matrix.html#translate">translate</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.PlanarSet.html">PlanarSet</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.PlanarSet.html#add">add</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.PlanarSet.html#clear">clear</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.PlanarSet.html#delete">delete</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.PlanarSet.html#hit">hit</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.PlanarSet.html#search">search</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.PlanarSet.html#svg">svg</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Point.html">Point</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#clone">clone</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#distanceTo">distanceTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#equalTo">equalTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#leftTo">leftTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#lessThan">lessThan</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#on">on</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#projectionOn">projectionOn</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#rotate">rotate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#svg">svg</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#toJSON">toJSON</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#transform">transform</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Point.html#translate">translate</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Polygon.html">Polygon</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#addFace">addFace</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#addVertex">addVertex</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#area">area</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#clone">clone</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#contains">contains</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#deleteFace">deleteFace</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#distanceTo">distanceTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#intersect">intersect</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#isEmpty">isEmpty</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#isValid">isValid</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#removeChain">removeChain</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#rotate">rotate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#svg">svg</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#toJSON">toJSON</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#transform">transform</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Polygon.html#translate">translate</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Ray.html">Ray</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Ray.html#clone">clone</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Ray.html#intersect">intersect</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Segment.html">Segment</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#clone">clone</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#contains">contains</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#distanceTo">distanceTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#equalTo">equalTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#intersect">intersect</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#isZeroLength">isZeroLength</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#middle">middle</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#reverse">reverse</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#rotate">rotate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#split">split</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#svg">svg</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#tangentInEnd">tangentInEnd</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#tangentInStart">tangentInStart</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#toJSON">toJSON</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#transform">transform</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Segment.html#translate">translate</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Flatten.Vector.html">Vector</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#add">add</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#angleTo">angleTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#clone">clone</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#cross">cross</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#dot">dot</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#equalTo">equalTo</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#invert">invert</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#multiply">multiply</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#normalize">normalize</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#projectionOn">projectionOn</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#rotate">rotate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#rotate90CCW">rotate90CCW</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#rotate90CW">rotate90CW</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#subtract">subtract</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Flatten.Vector.html#toJSON">toJSON</a></span></li><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-member">M</span><span class="nav-item-name"><a href="global.html#DP_TOL">DP_TOL</a></span></li>
</nav>
<div id="main">
<h1 class="page-title">classes/face.js</h1>
<section>
<article>
<pre class="prettyprint source linenums"><code>/**
* Created by Alex Bol on 3/17/2017.
*/
"use strict";
module.exports = function (Flatten) {
let {Point, point, Segment, segment, Arc, Box, Edge, Circle} = Flatten;
/**
* Class representing a face (closed loop) in a [polygon]{@link Flatten.Polygon} object.
* Face is a circular bidirectional linked list of [edges]{@link Flatten.Edge}.
* Face object cannot be instantiated with a constructor.
* Instead, use [polygon.addFace()]{@link Flatten.Polygon#addFace} method.
* <br/>
* Note, that face only set entry point to the linked list of edges but does not contain edges by itself.
* Container of edges is a property of the polygon object. <br/>
*
* @example
* // Face implements "next" iterator which enables to iterate edges in for loop:
* for (let edge of face) {
* console.log(edge.shape.length) // do something
* }
*
* // Instead, it is possible to iterate edges as linked list, starting from face.first:
* let edge = face.first;
* do {
* console.log(edge.shape.length); // do something
* edge = edge.next;
* } while (edge != face.first)
*/
Flatten.Face = class Face {
constructor(polygon, ...args) {
/**
* Reference to the first edge in face
*/
this.first;
/**
* Reference to the last edge in face
*/
this.last;
this._box = undefined; // new Box();
this._orientation = undefined;
if (args.length == 0) {
return;
}
/* If passed an array it supposed to be:
1) array of shapes that performs close loop or
2) array of points that performs set of vertices
*/
if (args.length == 1) {
if (args[0] instanceof Array) {
// let argsArray = args[0];
let shapes = args[0]; // argsArray[0];
if (shapes.length == 0)
return;
if (shapes.every((shape) => {
return shape instanceof Point
})) {
let segments = Face.points2segments(shapes);
this.shapes2face(polygon.edges, segments);
}
else if (shapes.every((shape) => {
return (shape instanceof Segment || shape instanceof Arc)
})) {
this.shapes2face(polygon.edges, shapes);
}
// this is from JSON.parse object
else if (shapes.every((shape) => {
return (shape.name === "segment" || shape.name === "arc")
})) {
let flattenShapes = [];
for (let shape of shapes) {
let flattenShape;
if (shape.name === "segment") {
flattenShape = new Segment(shape);
}
else {
flattenShape = new Arc(shape);
}
flattenShapes.push(flattenShape);
}
this.shapes2face(polygon.edges, flattenShapes);
}
}
/* Create new face and copy edges into polygon.edges set */
else if (args[0] instanceof Face) {
let face = args[0];
this.first = face.first;
this.last = face.last;
for (let edge of face) {
polygon.edges.add(edge);
}
}
/* Instantiate face from circle circle in CCW orientation */
else if (args[0] instanceof Circle) {
this.shapes2face(polygon.edges, [args[0].toArc(Flatten.CCW)]);
}
/* Instantiate face from a box in CCW orientation */
else if (args[0] instanceof Box) {
let box = args[0];
this.shapes2face(polygon.edges, [
segment(point(box.xmin, box.ymin), point(box.xmax, box.ymin)),
segment(point(box.xmax, box.ymin), point(box.xmax, box.ymax)),
segment(point(box.xmax, box.ymax), point(box.xmin, box.ymax)),
segment(point(box.xmin, box.ymax), point(box.xmin, box.ymin))
]);
}
}
/* If passed two edges, consider them as start and end of the face loop */
/* THIS METHOD WILL BE USED BY BOOLEAN OPERATIONS */
/* Assume that edges already copied to polygon.edges set in the clip algorithm !!! */
if (args.length == 2 && args[0] instanceof Edge && args[1] instanceof Edge) {
this.first = args[0]; // first edge in face or undefined
this.last = args[1]; // last edge in face or undefined
this.last.next = this.first;
this.first.prev = this.last;
// set arc length
this.setArcLength();
/*
let edge = this.first;
edge.arc_length = 0;
edge = edge.next;
while (edge !== this.first) {
edge.arc_length = edge.prev.arc_length + edge.prev.length;
edge = edge.next;
}
*/
// this.box = this.getBox();
// this.orientation = this.getOrientation(); // face direction cw or ccw
}
}
[Symbol.iterator]() {
let edge = undefined;
return {
next: () => {
let value = edge ? edge : this.first;
let done = this.first ? (edge ? edge === this.first : false) : true;
edge = value ? value.next : undefined;
return {value: value, done: done};
}
};
};
/**
* Return array of edges from first to last
* @returns {Array}
*/
get edges() {
let face_edges = [];
for (let edge of this) {
face_edges.push(edge);
}
return face_edges;
}
/**
* Return number of edges in the face
* @returns {number}
*/
get size() {
let counter = 0;
for (let edge of this) {
counter++;
}
return counter;
}
/**
* Return bounding box of the face
* @returns {Box}
*/
get box() {
if (this._box === undefined) {
let box = new Flatten.Box();
for (let edge of this) {
box = box.merge(edge.box);
}
this._box = box;
}
return this._box;
}
static points2segments(points) {
let segments = [];
for (let i = 0; i < points.length; i++) {
segments.push(new Segment(points[i], points[(i + 1) % points.length]));
}
return segments;
}
shapes2face(edges, shapes) {
for (let shape of shapes) {
let edge = new Edge(shape);
this.append(edges, edge);
// this.box = this.box.merge(shape.box);
// edges.add(edge);
}
// this.orientation = this.getOrientation(); // face direction cw or ccw
}
/**
* Returns true if face is empty, false otherwise
* @returns {boolean}
*/
isEmpty() {
return (this.first === undefined && this.last === undefined)
}
/**
* Append given edge after the last edge (and before the first edge). <br/>
* This method mutates current object and does not return any value
* @param {PlanarSet} edges - Container of edges
* @param {Edge} edge - Edge to be appended to the linked list
*/
append(edges, edge) {
if (this.first === undefined) {
edge.prev = edge;
edge.next = edge;
this.first = edge;
this.last = edge;
edge.arc_length = 0;
}
else {
// append to end
edge.prev = this.last;
this.last.next = edge;
// update edge to be last
this.last = edge;
// restore circular links
this.last.next = this.first;
this.first.prev = this.last;
// set arc length
edge.arc_length = edge.prev.arc_length + edge.prev.length;
}
edge.face = this;
edges.add(edge); // Add new edges into edges container
}
/**
* Insert edge newEdge into the linked list after the edge edgeBefore <br/>
* This method mutates current object and does not return any value
* @param {PlanarSet} edges - Container of edges
* @param {Edge} newEdge - Edge to be inserted into linked list
* @param {Edge} edgeBefore - Edge to insert newEdge after it
*/
insert(edges, newEdge, edgeBefore) {
if (this.first === undefined) {
newEdge.prev = newEdge;
newEdge.next = newEdge;
this.first = newEdge;
this.last = newEdge;
}
else {
/* set links to new edge */
let edgeAfter = edgeBefore.next;
edgeBefore.next = newEdge;
edgeAfter.prev = newEdge;
/* set links from new edge */
newEdge.prev = edgeBefore;
newEdge.next = edgeAfter;
/* extend chain if new edge added after last edge */
if (this.last === edgeBefore)
this.first = newEdge;
}
newEdge.face = this;
// set arc length
if (newEdge.prev === this.last) {
newEdge.arc_length = 0;
}
else {
newEdge.arc_length = newEdge.prev.arc_length + newEdge.prev.length;
}
edges.add(newEdge); // Add new edges into edges container
}
/**
* Remove the given edge from the linked list of the face <br/>
* This method mutates current object and does not return any value
* @param {PlanarSet} edges - Container of edges
* @param {Edge} edge - Edge to be removed
*/
remove(edges, edge) {
// special case if last edge removed
if (edge === this.first && edge === this.last) {
this.first = undefined;
this.last = undefined;
}
else {
// update linked list
edge.prev.next = edge.next;
edge.next.prev = edge.prev;
// update first if need
if (edge === this.first) {
this.first = edge.next;
}
// update last if need
if (edge === this.last) {
this.last = edge.prev;
}
}
edges.delete(edge); // delete from PlanarSet of edges and update index
}
/**
* Reverse orientation of the face: first edge become last and vice a verse,
* all edges starts and ends swapped, direction of arcs inverted.
*/
reverse() {
// collect edges in revert order with reverted shapes
let edges = [];
let edge_tmp = this.last;
do {
// reverse shape
edge_tmp.shape = edge_tmp.shape.reverse();
edges.push(edge_tmp);
edge_tmp = edge_tmp.prev;
} while (edge_tmp !== this.last);
// restore linked list
this.first = undefined;
this.last = undefined;
for (let edge of edges) {
if (this.first === undefined) {
edge.prev = edge;
edge.next = edge;
this.first = edge;
this.last = edge;
edge.arc_length = 0;
}
else {
// append to end
edge.prev = this.last;
this.last.next = edge;
// update edge to be last
this.last = edge;
// restore circular links
this.last.next = this.first;
this.first.prev = this.last;
// set arc length
edge.arc_length = edge.prev.arc_length + edge.prev.length;
}
}
// Recalculate orientation, if set
if (this._orientation !== undefined) {
this._orientation = undefined;
this._orientation = this.orientation();
}
}
/**
* Set arc_length property for each of the edges in the face.
* Arc_length of the edge it the arc length from the first edge of the face
*/
setArcLength() {
for (let edge of this) {
if (edge === this.first) {
edge.arc_length = 0.0;
}
else {
edge.arc_length = edge.prev.arc_length + edge.prev.length;
}
edge.face = this;
}
}
/**
* Returns the absolute value of the area of the face
* @returns {number}
*/
area() {
return Math.abs(this.signedArea());
}
/**
* Returns signed area of the simple face.
* Face is simple if it has no self intersections that change its orientation.
* Then the area will be positive if the orientation of the face is clockwise,
* and negative if orientation is counterclockwise.
* It may be zero if polygon is degenerated.
* @returns {number}
*/
signedArea() {
let sArea = 0;
let ymin = this.box.ymin;
for (let edge of this) {
sArea += edge.shape.definiteIntegral(ymin);
}
return sArea;
}
/**
* Return face orientation: one of Flatten.ORIENTATION.CCW, Flatten.ORIENTATION.CW, Flatten.ORIENTATION.NOT_ORIENTABLE <br/>
* According to Green theorem the area of a closed curve may be calculated as double integral,
* and the sign of the integral will be defined by the direction of the curve.
* When the integral ("signed area") will be negative, direction is counter clockwise,
* when positive - clockwise and when it is zero, polygon is not orientable.
* See {@link https://mathinsight.org/greens_theorem_find_area}
* @returns {number}
*/
orientation() {
if (this._orientation === undefined) {
let area = this.signedArea();
if (Flatten.Utils.EQ_0(area)) {
this._orientation = Flatten.ORIENTATION.NOT_ORIENTABLE;
}
else if (Flatten.Utils.LT(area, 0)) {
this._orientation = Flatten.ORIENTATION.CCW;
}
else {
this._orientation = Flatten.ORIENTATION.CW;
}
}
return this._orientation;
}
/**
* Returns true if face of the polygon is simple (no self-intersection points found)
* NOTE: this method is incomplete because it doe not exclude touching points
* Real self intersection inverts orientation of the polygon.
* But this is also good enough for the demonstration of the idea
* @param {Edges} edges - reference to polygon.edges to provide search index
* @returns {boolean}
*/
isSimple(edges) {
let ip = Face.getSelfIntersections(this, edges, true);
return ip.length == 0;
}
static getSelfIntersections(face, edges, exitOnFirst = false) {
let int_points = [];
// calculate intersections
for (let edge1 of face) {
// request edges of polygon in the box of edge1
let resp = edges.search(edge1.box);
// for each edge2 in response
for (let edge2 of resp) {
// Skip itself
if (edge1 === edge2)
continue;
// Skip next and previous edge if both are segment (if one of them arc - calc intersection)
if (edge1.shape instanceof Flatten.Segment && edge2.shape instanceof Flatten.Segment &&
(edge1.next === edge2 || edge1.prev === edge2))
continue;
// calculate intersections between edge1 and edge2
let ip = edge1.shape.intersect(edge2.shape);
// for each intersection point
for (let pt of ip) {
// skip start-end connections
if (pt.equalTo(edge1.start) && pt.equalTo(edge2.end) && edge2 === edge1.prev)
continue;
if (pt.equalTo(edge1.end) && pt.equalTo(edge2.start) && edge2 === edge1.next)
continue;
int_points.push(pt);
if (exitOnFirst)
break;
}
if (int_points.length > 0 && exitOnFirst)
break;
}
if (int_points.length > 0 && exitOnFirst)
break;
}
return int_points;
}
toJSON() {
return this.edges.map(edge => edge.toJSON());
}
/**
* Returns string to be assigned to "d" attribute inside defined "path"
* @returns {string}
*/
svg() {
let svgStr = `\nM${this.first.start.x},${this.first.start.y}`;
for (let edge of this) {
svgStr += edge.svg();
}
svgStr += ` z`;
return svgStr;
}
};
};</code></pre>
</article>
</section>
</div>
<br class="clear">
<footer>
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> on Fri Dec 07 2018 09:41:42 GMT+0200 (Jerusalem Standard Time) using the Minami theme.
</footer>
<script>prettyPrint();</script>
<script src="scripts/linenumber.js"></script>
</body>
</html>