/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: UniformGrid.java
* Written by Team 4: Benedikt Mueller, Richard Fallert
*
* This code has been developed at the Karlsruhe Institute of Technology (KIT), Germany,
* as part of the course "Multicore Programming in Practice: Tools, Models, and Languages".
* Contact instructor: Dr. Victor Pankratius (pankratius@ipd.uka.de)
*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.placement.genetic2;
import com.sun.electric.tool.placement.PlacementFrame.PlacementNode;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* This is a data structure for the acceleration of collision detection,
* it speeds up the calculation of overlap area.
* @see DeltaIndividual
*/
public class UniformGrid
{
LinkedList<Integer>[][] grid;
LinkedList<Integer>[] cellOfNode;
// bounding box of the reference placement.
double left;
double right;
double top;
double bottom;
double cellW; // maximum width OR height of all PlacementNodes in the reference placement.
int w, h; // grid size
UniformGrid(List<PlacementNode> nodesToPlace, double left, double right, double top, double bottom, double cellW)
{
cellOfNode = new LinkedList[nodesToPlace.size()];
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
this.cellW = cellW;
w = Math.max((int)Math.ceil((right-left)/cellW), 1);
h = Math.max((int)Math.ceil((top-bottom)/cellW), 1);
// System.out.println("Grid size w: " + w + " h: " + h);
grid = new LinkedList[w][h];
}
public int getCellX(double xPos)
{
int x = (int)((xPos-left)/cellW);
if(x < 0) x = 0;
if(x >= w) x = w-1;
return x;
}
public int getCellY(double yPos)
{
int y = (int)((yPos-bottom)/cellW);
if(y < 0) y = 0;
if(y >= h) y = h-1;
return y;
}
/**
* Insert index for a PlacementNode.
* @param i index of the PlacementNode.
* @param xPos x-coordinate of the PlacementNode.
* @param yPos y-coordinate of the PlacementNode.
*/
public LinkedList<Integer> insert(int i, double xPos, double yPos)
{
int x = getCellX(xPos);
int y = getCellY(yPos);
if(grid[x][y] == null)
{
grid[x][y] = new LinkedList<Integer>();
}
grid[x][y].add(new Integer(i));
cellOfNode[i] = grid[x][y];
LinkedList<Integer> cellList = cellOfNode[i];
return cellList;
}
public void remove(int nodeIndex)
{
LinkedList<Integer> cellList = cellOfNode[nodeIndex];
//System.out.println("before: " + cellList);
if(cellList == null) System.out.println("ARRAY PANIC in remove in UniformGrid");
Iterator<Integer> it = cellList.iterator();
while(it.hasNext())
{
if(it.next().intValue() == nodeIndex)
{
it.remove();
//System.out.println("after: " + cellList);
return;
}
}
}
/**
* Gets the change in collision area for the delta-position of the delta-block.
* ( Compared to the original position of the PlacementNode in the reference placement. )
* @param b Delta-block whose overlap is to be updated.
* @param deltas List of all delta-blocks.
* @param nodesToPlace All PlacementNodes of the reference placement.
* @param overlaps Partial overlaps for potential diversity comparison in the evolution.
*/
public double collide(Block b, List<Block> deltas, List<PlacementNode> nodesToPlace, double[] overlaps)
{
double overlap = 0.0;
int x = getCellX(b.getX());
int y = getCellY(b.getY());
Block orig = new Block();
orig.valuesFrom(nodesToPlace.get(b.getNr()));
orig.number = b.getNr();
int oldX = getCellX(orig.getX());
int oldY = getCellY(orig.getY());
// check the cell to which the Block belongs and its 8 neighbors for collision.
// This is done first to calculate the new collision and a second time to subtract
// the overlap of the original of the deltablock in the reference placement.
for(int i = -1; i <= 1; i++)
{
for(int j = -1; j <= 1; j++)
{
// new overlap:
overlap += collideCell(b, deltas, nodesToPlace, overlaps, x+i, y+j, false);
// old overlap of original:
overlap -= collideCell(orig, deltas, nodesToPlace, overlaps, oldX+i, oldY+j, true);
}
}
return overlap;
}
/**
* Gets the change in collision area for the delta-block in a single grid cell.
* @param b Delta-block whose overlap is to be updated.
* @param deltas List of all delta-blocks.
* @param nodesToPlace All PlacementNodes of the reference placement.
* @param overlaps Partial overlaps for potential diversity comparison in the evolution.
* @param x x-coordinate of the grid cell to check for collisions.
* @param y y-coordinate of the grid cell.
*/
public double collideCell(Block b, List<Block> deltas, List<PlacementNode> nodesToPlace,
double[] overlaps, int x, int y, boolean oldBlock)
{
if(x < 0 || x >= w || y < 0 || y >= h) return 0.0;
if(grid[x][y] == null) return 0.0;
double overlap = 0.0;
Block other = new Block();
Iterator<Block> iB = deltas.iterator();
Block deltaBlock = iB.next();
for(Integer i : grid[x][y])
{
if(i.intValue() != b.getNr())
{
other.valuesFrom(nodesToPlace.get(i.intValue()));
while(deltaBlock.getNr() < i.intValue() && iB.hasNext())
{
deltaBlock = iB.next();
}
if(deltaBlock.getNr() != i.intValue()) // only collide with the non-deltas. the deltas don't use this grid
{
//overlap -= orig.intersectionArea(other);
overlap += b.intersectionArea(other);
if(oldBlock)
{
overlaps[b.getNr()] -= b.intersectionArea(other);
}
else
{
overlaps[b.getNr()] += b.intersectionArea(other);
}
}
}
}
return overlap;
}
/**
* Gets the collision area for the Block b with the previous nodes.
* ( Compared to the original position of the PlacementNode in the reference placement. )
* @param nodesToPlace All PlacementNodes of the reference placement.
* @param overlaps Partial overlaps for potential diversity comparison in the evolution.
*/
public double collide(int nodeId, List<PlacementNode> nodesToPlace, double[] overlaps)
{
double overlap = 0.0;
PlacementNode n = nodesToPlace.get(nodeId);
Block b = new Block();
b.valuesFrom(n);
b.number = nodeId;
int x = getCellX(b.getX());
int y = getCellY(b.getY());
// check the cell to which the Block belongs and its 8 neighbors for collision.
for(int i = -1; i <= 1; i++)
{
for(int j = -1; j <= 1; j++)
{
// double t = overlap;
overlap += collideCell(b, nodesToPlace, overlaps, x+i, y+j);
}
}
return overlap;
}
/**
* Gets the collision area for the Block b with the previous nodes.
* @param b The values of a PlacementNode, inserted into a block.
* @param nodesToPlace All PlacementNodes of the reference placement.
* @param overlaps Partial overlaps for potential diversity comparison in the evolution.
* @param x x-coordinate of the grid cell to check for collisions.
* @param y y-coordinate of the grid cell.
*/
public double collideCell(Block b, List<PlacementNode> nodesToPlace,
double[] overlaps, int x, int y)
{
if(x < 0 || x >= w || y < 0 || y >= h) return 0.0;
if(grid[x][y] == null) return 0.0;
double overlap = 0.0;
Block other = new Block();
for(Integer i : grid[x][y])
{
if(i.intValue() >= b.getNr()) return overlap;
other.valuesFrom(nodesToPlace.get(i.intValue()));
overlap += b.intersectionArea(other);
overlaps[b.getNr()] += b.intersectionArea(other);
}
return overlap;
}
public void draw(Graphics g, double scale)
{
for(int i = 0; i < w; i++)
{
for(int j = 0; j < h; j++)
{
g.setColor(new Color(i/(float)w, j/(float)h, 0.3f, 0.7f));
//g.fillRect((int)(left*scale+i*cellW*scale), (int)(bottom*scale+j*cellW*scale), (int)(cellW*scale), (int)(cellW*scale));
g.drawRect((int)(left*scale+i*cellW*scale), (int)(bottom*scale+j*cellW*scale), (int)(cellW*scale), (int)(cellW*scale));
g.drawString("("+i+","+j+")", (int)(left*scale+i*cellW*scale), (int)(bottom*scale+j*cellW*scale));
}
}
}
}