Flag normals to ignore for collision responses.

Finds, builds and stores neighbouring edges leading into and out of each tile as part of this process.

@param {Phaser.Tilemaps.Tile[]} tiles - The tiles to flag ignormals for.
355868
function (tiles) {
		const maxDist = 5;
		
		let t, tile, tileBody, tileVertices, n, neighbour, neighbourBody, neighbourVertices, i, j, tv0, tv1, tv2, tv3, nv1, nv2, edge;
		
		for (t = 0; t < tiles.length; t++) {
			tile = tiles[t];
			
			// Skip over irrelevant tiles
			if (isIrrelevant(tile)) {
				continue;
			}
			
			// Grab the tile's body and vertices to build its edges and compare with neighbours
			tileBody = tile.physics.matterBody.body;
			tileVertices = tileBody.vertices;
			
			tileBody.edges = [];
			tileBody.ignormals = [];
			
			for (i = 0; i < tileVertices.length; i++) {
				tv1 = tileVertices[i];
				tv2 = tileVertices[(i + 1) % tileVertices.length];
				
				// Find or build the edge for this tile vertex
				edge = tileBody.edges[i];
				
				// Build the edge
				edge = buildEdge(tv1, tv2, tileBody);
				edge.ignore = tv1.isInternal;
				
				// Add it to the tile's edge list
				tileBody.edges[i] = edge;
			}
			
			for (n in tile.physics.slopes.neighbours) {
				neighbour = tile.physics.slopes.neighbours[n];
				
				// Skip over irrelevant neighbouring tiles
				if (isIrrelevant(neighbour)) {
					continue;
				}
				
				// Grab the neighbour's body and vertices
				neighbourBody = neighbour.physics.matterBody.body;
				neighbourVertices = neighbourBody.vertices;
				
				// Skip over tile-neighbour pairs that don't overlap
				if (!Bounds.overlaps(tileBody.bounds, neighbourBody.bounds)) {
					continue;
				}
				
				// Iterate over the vertices of both the tile and its neighbour
				for (i = 0; i < tileVertices.length; i++) {
					tv1 = tileVertices[i];
					tv2 = tileVertices[(i + 1) % tileVertices.length];
					
					// Find the edge for this tile vertex
					edge = tileBody.edges[i];
					
					// Find neighbouring edges leading into this vertex
					for (j = 0; j < neighbourVertices.length; j++) {
						nv1 = neighbourVertices[j];
						nv2 = neighbourVertices[(j + 1) % neighbourVertices.length];
						
						// Skip internal neighbouring edges
						if (nv1.isInternal) {
							continue;
						}
						
						// Check for a leading or trailing ghost edges
						let leadingEdge = distance(tv1, nv2) < maxDist;
						let trailingEdge = distance(tv2, nv1) < maxDist;
						
						if (leadingEdge || trailingEdge) {
							// Add leading/trailing edge vertices
							if (leadingEdge && !edge.vertices[0]) {
								edge.vertices[0] = buildEdgeVertex(0, nv1.x, nv1.y, tileBody, true);
								
								// Link edges to each other
								if (neighbourBody.edges) {
									edge.prev = neighbourBody.edges[j];
									neighbourBody.edges[j].next = edge;
								}
							}
							
							if (trailingEdge && !edge.vertices[3]) {
								edge.vertices[3] = buildEdgeVertex(3, nv2.x, nv2.y, tileBody, true);
							}
							
							// Find the ignormals
							let ignormalVertex = leadingEdge ? nv2 : nv1;
							let tileEdgeNormal = tileBody.axes[i];
							let neighbourEdgeNormal = neighbourBody.axes[j];
							let ignormalCandidate = Vector.dot(tileEdgeNormal, neighbourEdgeNormal) > 0;// && !isAxisAligned(tileEdgeNormal) && !isAxisAligned(neighbourEdgeNormal);
							
							// If the tile edge normal and its neighbouring ghost edge normal are less than
							// 90 degrees different, we can set ignormals based on which bounds the joining
							// vertex lands on
							if (ignormalCandidate) {
								/**
								 * If the joining vertex is on a bounds edge, and the normal of its edge and the
								 * the neighbouring edge are not exactly the same as the corresponding direction
								 * constant, we can add an axis aligned ignormal
								 */
								
								// Leftwards ignormal
								if (Math.abs(ignormalVertex.x - tileBody.bounds.min.x) < 1 && !containsNormal(Constants.Directions.LEFT, tileBody.axes) && Vector.dot(tileEdgeNormal, Constants.Directions.LEFT) < 1 && Vector.dot(neighbourEdgeNormal, Constants.Directions.LEFT) < 1) {
									tileBody.ignormals.push(Constants.Directions.LEFT);
								}
								
								// Upwards ignormal
								if (Math.abs(ignormalVertex.y - tileBody.bounds.min.y) < 1 && !containsNormal(Constants.Directions.UP, tileBody.axes) && Vector.dot(tileEdgeNormal, Constants.Directions.UP) < 1 && Vector.dot(neighbourEdgeNormal, Constants.Directions.UP) < 1) {
									tileBody.ignormals.push(Constants.Directions.UP);
								}
								
								// Rightwards ignormal
								if (Math.abs(ignormalVertex.x - tileBody.bounds.max.x) < 1 && !containsNormal(Constants.Directions.RIGHT, tileBody.axes) && Vector.dot(tileEdgeNormal, Constants.Directions.RIGHT) < 1 && Vector.dot(neighbourEdgeNormal, Constants.Directions.RIGHT) < 1) {
									tileBody.ignormals.push(Constants.Directions.RIGHT);
								}
								
								// Downwards ignormal
								if (Math.abs(ignormalVertex.y - tileBody.bounds.max.y) < 1 && !containsNormal(Constants.Directions.DOWN, tileBody.axes) && Vector.dot(tileEdgeNormal, Constants.Directions.DOWN) < 1 && Vector.dot(neighbourEdgeNormal, Constants.Directions.DOWN) < 1) {
									tileBody.ignormals.push(Constants.Directions.DOWN);
								}
							}
						}
					}
				}
			}
			
			// Resolve edge normal data, now that we've seen all the neighbours
			// and ensure ghost vertices are set on each edge
			for (i = 0; i < tileVertices.length; i++) {
				edge = tileBody.edges[i];
				
				if (edge.ignore) {
					continue;
				}
				
				tv0 = tileVertices[((i - 1) % tileVertices.length + tileVertices.length) % tileVertices.length];
				tv1 = tileVertices[i];
				tv2 = tileVertices[(i + 1) % tileVertices.length];
				tv3 = tileVertices[(i + 2) % tileVertices.length];
				
				// Use this body's vertices as ghost vertices if neighbours
				// haven't provided them, and if they aren't internal edges
				if (!edge.vertices[0] && !tv0.isInternal) {
					edge.vertices[0] = buildEdgeVertex(0, tv0.x, tv0.y, tileBody, true);
				}
				
				if (!edge.vertices[3] && !tv2.isInternal) {
					edge.vertices[3] = buildEdgeVertex(3, tv3.x, tv3.y, tileBody, true);
				}
				
				// Calculate edge normals
				edge.normals = Axes.fromVertices(edge.vertices);
				
				// Calculate edge normal ranges
				buildEdgeNormalRanges(edge);
			}
		}
	}
214334
function (x, y, v) {
            var ret = v || new me.Vector2d();

            if (this.staggerX) { //flat top
                x -= this.staggerEven ? this.tilewidth : this.sideoffsetx;
            }
            else { //pointy top
                y -= this.staggerEven ? this.tileheight : this.sideoffsety;
            }

            // Start with the coordinates of a grid-aligned tile
            var referencePoint = me.pool.pull("me.Vector2d",
                Math.floor(x / (this.columnwidth * 2)),
                Math.floor((y / (this.rowheight * 2)))
            );

            // Relative x and y position on the base square of the grid-aligned tile
            var rel = me.pool.pull("me.Vector2d",
                x - referencePoint.x * (this.columnwidth * 2),
                y - referencePoint.y * (this.rowheight * 2)
            );

            // Adjust the reference point to the correct tile coordinates
            if (this.staggerX) {
                referencePoint.x = referencePoint.x * 2;
                if (this.staggerEven) {
                    ++referencePoint.x;
                }
            }
            else {
                referencePoint.y = referencePoint.y * 2;
                if (this.staggerEven) {
                    ++referencePoint.y;
                }
            }

            // Determine the nearest hexagon tile by the distance to the center
            var left, top, centerX, centerY;
            if (this.staggerX) {
                left = this.sidelengthx / 2;
                centerX = left + this.columnwidth;
                centerY = this.tileheight / 2;

                this.centers[0].set(left, centerY);
                this.centers[1].set(centerX, centerY - this.rowheight);
                this.centers[2].set(centerX, centerY + this.rowheight);
                this.centers[3].set(centerX + this.columnwidth, centerY);
            }
            else {
                top = this.sidelengthy / 2;
                centerX = this.tilewidth / 2;
                centerY = top + this.rowheight;

                this.centers[0].set(centerX, top);
                this.centers[1].set(centerX - this.columnwidth, centerY);
                this.centers[2].set(centerX + this.columnwidth, centerY);
                this.centers[3].set(centerX, centerY + this.rowheight);
            }

            var nearest = 0;
            var minDist = Number.MAX_VALUE;
            for (var i = 0; i < 4; ++i) {
                var dc = this.centers[i].sub(rel).length2();
                if (dc < minDist) {
                    minDist = dc;
                    nearest = i;
                }
            }

            var offsets = (this.staggerX) ? offsetsStaggerX : offsetsStaggerY;

            ret.set(
                referencePoint.x + offsets[nearest].x,
                referencePoint.y + offsets[nearest].y
            );

            me.pool.push(referencePoint);
            me.pool.push(rel);

            return ret;
        }
1264209
function isIrrelevant(tile) {
	return !tile
		|| !tile.physics
		|| !tile.physics.matterBody
		|| !tile.physics.matterBody.body
		|| !tile.physics.matterBody.body.vertices
		|| !tile.physics.slopes
		|| !tile.physics.slopes.neighbours
		|| !tile.physics.slopes.edges;
}
854468
def edges(inputtiles, parsenames):
    
    try:
        inputtiles = click.open_file(inputtiles).readlines()
    except IOError:
        inputtiles = [inputtiles]

    # parse the input stream into an array
    tiles = edge_finder.findedges(inputtiles, parsenames)

    for t in tiles:
        click.echo(t.tolist())
751386
protected FringeTile composeFringeTile (FringerRec[] fringers,
        Map<FringeTile, WeakReference<FringeTile>> fringes, int hashValue, boolean passable,
        Map<Long, BufferedImage> masks)
    {
        // sort the array so that higher priority fringers get drawn first
        QuickSort.sort(fringers);

        // Generate an identifier for the fringe tile being created as an array of the keys of its
        // component tiles in the order they'll be drawn in the fringe tile.
        List<Long> keys = Lists.newArrayList();
        for (FringerRec fringer : fringers) {
            int[] indexes = getFringeIndexes(fringer.bits);
            FringeConfiguration.FringeTileSetRecord tsr = _fringeconf.getFringe(
                fringer.baseset, hashValue);
            int fringeset = tsr.fringe_tsid;
            for (int index : indexes) {
                // Add a key for this tile as a long containing its base tile, the fringe set it's
                // working with and the index used in that set.
                keys.add((((long)fringer.baseset) << 32) + (fringeset << 16) + index);
            }
        }
        long[] fringeId = new long[keys.size()];
        for (int ii = 0; ii < fringeId.length; ii++) {
            fringeId[ii] = keys.get(ii);
        }
        FringeTile frTile = new FringeTile(fringeId, passable);

        // If the fringes map contains something with the same fringe identifier, this will pull
        // it out and we can use it instead.
        WeakReference<FringeTile> result = fringes.get(frTile);
        if (result != null) {
            FringeTile fringe = result.get();
            if (fringe != null) {
                return fringe;
            }
        }

        // There's no fringe with he same identifier, so we need to create the tile.
        BufferedImage img = null;
        for (FringerRec fringer : fringers) {
            int[] indexes = getFringeIndexes(fringer.bits);
            FringeConfiguration.FringeTileSetRecord tsr = _fringeconf.getFringe(
                fringer.baseset, hashValue);
            for (int index : indexes) {
                try {
                    img = getTileImage(img, tsr, fringer.baseset, index, hashValue, masks);
                } catch (NoSuchTileSetException nstse) {
                    log.warning("Autofringer couldn't find a needed tileset", nstse);
                }
            }
        }
        frTile.setImage(new BufferedMirage(img));
        fringes.put(frTile, new WeakReference<FringeTile>(frTile));
        return frTile;
    }
303293
function nextTile()
    {
        clog('nextTile');
        rect.emit('tile', tile);
        tile = {};
        if (rect.tilex < rect.widthTiles)
        {
            rect.tilex++;
            //clog([rect.tilex, rect.tiley]);
            return cli.readHextileTile(rect, cb);
        } else {
            clog('===================== new row! ' + rect.tiley);
            rect.tilex = 0;
            if (rect.tiley < rect.heightTiles)
            {
                rect.tiley++;
                //clog([rect.tilex, rect.tiley]);
                return cli.readHextileTile(rect, cb);
            } else {
                clog('====================')
                clog(rect);
                return cb();
            }
        }   
    }
996999
function tileToBBOX(tile) {
    var e = tile2lon(tile[0] + 1, tile[2]);
    var w = tile2lon(tile[0], tile[2]);
    var s = tile2lat(tile[1] + 1, tile[2]);
    var n = tile2lat(tile[1], tile[2]);
    return [w, s, e, n];
}
1015735
function hasSiblings(tile, tiles) {
    var siblings = getSiblings(tile);
    for (var i = 0; i < siblings.length; i++) {
        if (!hasTile(tiles, siblings[i])) return false;
    }
    return true;
}
638199
function(prepend, tileSize) {
        var grid = this.grid;
        var rowIndex = prepend ? 0 : (grid.length - 1);
        var sign = prepend ? -1 : 1;
        var rowSign = this.rowSign;
        var tileLayout = this.gridLayout;
        tileLayout.startrow += sign * rowSign;

        var modelRow = grid[rowIndex];
        var row = grid[prepend ? 'pop' : 'shift']();
        for (var i=0, len=row.length; i<len; i++) {
            var tile = row[i];
            var position = modelRow[i].position.clone();
            position.y += tileSize.h * sign;
            tile.moveTo(this.getTileBoundsForGridIndex(rowIndex, i), position);
        }
        grid[prepend ? 'unshift' : 'push'](row);
    }
653388
function() {
        var buffer = this.buffer + 1;
        while(true) {
            var tlTile = this.grid[0][0];
            var tlViewPort = {
                x: tlTile.position.x +
                    this.map.layerContainerOriginPx.x,
                y: tlTile.position.y +
                    this.map.layerContainerOriginPx.y
            };
            var ratio = this.getServerResolution() / this.map.getResolution();
            var tileSize = {
                w: Math.round(this.tileSize.w * ratio),
                h: Math.round(this.tileSize.h * ratio)
            };
            if (tlViewPort.x > -tileSize.w * (buffer - 1)) {
                this.shiftColumn(true, tileSize);
            } else if (tlViewPort.x < -tileSize.w * buffer) {
                this.shiftColumn(false, tileSize);
            } else if (tlViewPort.y > -tileSize.h * (buffer - 1)) {
                this.shiftRow(true, tileSize);
            } else if (tlViewPort.y < -tileSize.h * buffer) {
                this.shiftRow(false, tileSize);
            } else {
                break;
            }
        }
    }
186481
function(map) {
        if (this._destroyed || !OpenLayers.Layer.Grid) {
            return;
        }
        this.maps.push(map);
        this.tileQueue[map.id] = [];
        for (var i=0, ii=map.layers.length; i<ii; ++i) {
            this.addLayer({layer: map.layers[i]});
        }
        map.events.on({
            move: this.move,
            zoomend: this.zoomEnd,
            changelayer: this.changeLayer,
            addlayer: this.addLayer,
            preremovelayer: this.removeLayer,
            scope: this
        });
    }
1076442
function(evt) {
        var layer = evt.object;
        var tileQueue = this.tileQueue[layer.map.id];
        for (var i=tileQueue.length-1; i>=0; --i) {
            if (tileQueue[i].layer === layer) {
                tileQueue.splice(i, 1);
            }
        }
    }
1294871
function getChildren(tile) {
    return [
        [tile[0] * 2, tile[1] * 2, tile[2] + 1],
        [tile[0] * 2 + 1, tile[1] * 2, tile[2 ] + 1],
        [tile[0] * 2 + 1, tile[1] * 2 + 1, tile[2] + 1],
        [tile[0] * 2, tile[1] * 2 + 1, tile[2] + 1]
    ];
}
1247036
function createTile(coords, done) {
    let key = this._tileCoordsToKey(coords);
    // console.log('Need:', key);
    
    if ( key in this._freshTiles ) {
      let tile = this._freshTiles[ key ].pop();
      if ( !this._freshTiles[ key ].length ) {
        delete this._freshTiles[ key ];
      }
      L.Util.requestAnimFrame(done);
      // 			console.log('Got ', key, ' from _freshTiles');
      return tile;
    }
    let tileContainer = L.DomUtil.create("div");
    this._tileCallbacks[ key ] = this._tileCallbacks[ key ] || [];
    this._tileCallbacks[ key ].push(
      (function(c /* , k*/) {
        return function(imgNode) {
          let parent = imgNode.parentNode;
          if ( parent ) {
            parent.removeChild(imgNode);
            parent.removeChild = L.Util.falseFn;
            // 						imgNode.parentNode.replaceChild(L.DomUtil.create('img'), imgNode);
          }
          c.appendChild(imgNode);
          done();
          // 					console.log('Sent ', k, ' to _tileCallbacks');
        };
      })(tileContainer /* , key*/)
    );
    
    return tileContainer;
  }
483500
function(instance, searchNode, x, y, cost) {
		var adjacentCoordinateX = searchNode.x+x;
		var adjacentCoordinateY = searchNode.y+y;
		
		if (instance.endX === adjacentCoordinateX && instance.endY === adjacentCoordinateY) {
			instance.isDoneCalculating = true;
			var path = [];
			var pathLen = 0;
			path[pathLen] = {x: adjacentCoordinateX, y: adjacentCoordinateY};
			pathLen++;
			path[pathLen] = {x: searchNode.x, y:searchNode.y};
			pathLen++;
			var parent = searchNode.parent;
			while (parent!=null) {
				path[pathLen] = {x: parent.x, y:parent.y};
				pathLen++;
				parent = parent.parent;
			}
			path.reverse();
			instance.callback(path);
		}

		if (pointsToAvoid[adjacentCoordinateX + "_" + adjacentCoordinateY] === undefined) {
			for (var i = 0; i < acceptableTiles.length; i++) {
				if (collisionGrid[adjacentCoordinateY][adjacentCoordinateX] === acceptableTiles[i]) {
					
					var node = coordinateToNode(instance, adjacentCoordinateX, 
						adjacentCoordinateY, searchNode, cost);
					
					if (node.list === undefined) {
						node.list = EasyStar.Node.OPEN_LIST;
						instance.openList.insert(node);
					} else if (node.list === EasyStar.Node.OPEN_LIST) {
						if (searchNode.costSoFar + cost < node.costSoFar) {
							node.costSoFar = searchNode.costSoFar + cost;
							node.parent = searchNode;
						}
					}
					break;
				}
			}

		}
	}
498389
function (renderer, x, y, tmxTile) {
            var tileset = tmxTile.tileset;
            // draw the tile
            tileset.drawTile(
                renderer,
                ((this.cols - 1) * tileset.tilewidth + (x - y) * tileset.tilewidth >> 1),
                (-tileset.tilewidth + (x + y) * tileset.tileheight >> 2),
                tmxTile
            );
        }
857996
private void updateTile(Collection<Tile> resolved, Collection<Tile> toResolve, Tile tile, int ox, int oy)
    {
        final int tx = tile.getInTileX();
        final int ty = tile.getInTileY();

        final Tile neighbor = map.getTile(tx + ox, ty + oy);
        if (neighbor != null)
        {
            updateNeigbor(resolved, toResolve, tile, neighbor, ox, oy);
        }
    }