docs: function(polygon) {
              var result = {
                  type: null,
                  front: null,
                  back: null
              };
              // cache in local vars (speedup):
              var planenormal = this.normal;
              var vertices = polygon.vertices;
              var numvertices = vertices.length;
              if (polygon.plane.equals(this)) {
                  result.type = 0;
              } else {
                  var EPS = CSG.Plane.EPSILON;
                  var thisw = this.w;
                  var hasfront = false;
                  var hasback = false;
                  var vertexIsBack = [];
                  var MINEPS = -EPS;
                  for (var i = 0; i < numvertices; i++) {
                      var t = planenormal.dot(vertices[i].pos) - thisw;
                      var isback = (t < 0);
                      vertexIsBack.push(isback);
                      if (t > EPS) hasfront = true;
                      if (t < MINEPS) hasback = true;
                  }
                  if ((!hasfront) && (!hasback)) {
                      // all points coplanar
                      var t = planenormal.dot(polygon.plane.normal);
                      result.type = (t >= 0) ? 0 : 1;
                  } else if (!hasback) {
                      result.type = 2;
                  } else if (!hasfront) {
                      result.type = 3;
                  } else {
                      // spanning
                      result.type = 4;
                      var frontvertices = [],
                          backvertices = [];
                      var isback = vertexIsBack[0];
                      for (var vertexindex = 0; vertexindex < numvertices; vertexindex++) {
                          var vertex = vertices[vertexindex];
                          var nextvertexindex = vertexindex + 1;
                          if (nextvertexindex >= numvertices) nextvertexindex = 0;
                          var nextisback = vertexIsBack[nextvertexindex];
                          if (isback == nextisback) {
                              // line segment is on one side of the plane:
                              if (isback) {
                                  backvertices.push(vertex);
                              } else {
                                  frontvertices.push(vertex);
                              }
                          } else {
                              // line segment intersects plane:
                              var point = vertex.pos;
                              var nextpoint = vertices[nextvertexindex].pos;
                              var intersectionpoint = this.splitLineBetweenPoints(point, nextpoint);
                              var intersectionvertex = new CSG.Vertex(intersectionpoint);
                              if (isback) {
                                  backvertices.push(vertex);
                                  backvertices.push(intersectionvertex);
                                  frontvertices.push(intersectionvertex);
                              } else {
                                  frontvertices.push(vertex);
                                  frontvertices.push(intersectionvertex);
                                  backvertices.push(intersectionvertex);
                              }
                          }
                          isback = nextisback;
                      } // for vertexindex
                      // remove duplicate vertices:
                      var EPS_SQUARED = CSG.Plane.EPSILON * CSG.Plane.EPSILON;
                      if (backvertices.length >= 3) {
                          var prevvertex = backvertices[backvertices.length - 1];
                          for (var vertexindex = 0; vertexindex < backvertices.length; vertexindex++) {
                              var vertex = backvertices[vertexindex];
                              if (vertex.pos.distanceToSquared(prevvertex.pos) < EPS_SQUARED) {
                                  backvertices.splice(vertexindex, 1);
                                  vertexindex--;
                              }
                              prevvertex = vertex;
                          }
                      }
                      if (frontvertices.length >= 3) {
                          var prevvertex = frontvertices[frontvertices.length - 1];
                          for (var vertexindex = 0; vertexindex < frontvertices.length; vertexindex++) {
                              var vertex = frontvertices[vertexindex];
                              if (vertex.pos.distanceToSquared(prevvertex.pos) < EPS_SQUARED) {
                                  frontvertices.splice(vertexindex, 1);
                                  vertexindex--;
                              }
                              prevvertex = vertex;
                          }
                      }
                      if (frontvertices.length >= 3) {
                          result.front = new CSG.Polygon(frontvertices, polygon.shared, polygon.plane);
                      }
                      if (backvertices.length >= 3) {
                          result.back = new CSG.Polygon(backvertices, polygon.shared, polygon.plane);
                      }
                  }
              }
              return result;
          }