/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Block.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 com.sun.electric.util.math.Orientation;
import java.util.Random;
/**
* A Block is a simplified PlacementNode for the genome of an Individual in a genetic algorithm.
* @see Individual
*/
public class Block implements Comparable<Block>
{
Orientation o;
private double width, height, halfWidth, halfHeight;
private double xPos, yPos;
int number = -1; // index of the PlacementNode to which this Block corresponds to
public Block()
{
}
public Block(Block b)
{
xPos = b.xPos;
yPos = b.yPos;
width = b.width;
height = b.height;
halfWidth = b.halfWidth;
halfHeight = b.halfHeight;
o = b.o;
number = b.number;
}
public Block(double x, double y, double w, double h)
{
width = w;
halfWidth = width/2.0;
height = h;
halfHeight = height/2.0;
xPos = x;
yPos = y;
o = Orientation.IDENT;
}
public Block(double x, double y, double w, double h, Orientation o, int number)
{
width = w;
halfWidth = width/2.0;
height = h;
halfHeight = height/2.0;
xPos = x;
yPos = y;
this.o = o;
this.number = number;
}
public void valuesFrom(PlacementNode n)
{
xPos = n.getPlacementX();
yPos = n.getPlacementY();
width = n.getWidth();
halfWidth = width/2.0;
height = n.getHeight();
halfHeight = height/2.0;
o = n.getPlacementOrientation();
}
/**
* Method to compare the number of blocks
* @param other The other Block
* @return -1 if other has a higher number, 1 if other has lower one, else 0.
*/
public int compareTo(Block other)
{
if(getNr() < other.getNr())
{
return -1;
}
else if(getNr() > other.getNr())
{
return 1;
}
else return 0;
}
/**
* Method to get the index of the node to which this Block corresponds.
* @return The index of the corresponding node in the nodesToPlace list.
*/
public int getNr() { return number; }
public Orientation getOrientation()
{
return o;
}
public void setOrientation(Orientation o)
{
this.o = o;
}
/**
* Method to return the width of this Block.
* @return the width of this Block.
*/
public double getWidth()
{
return width;
}
/**
* Method to return the height of this Block.
* @return the height of this Block.
*/
public double getHeight()
{
return height;
}
/**
* Method to return the x-coordinate of this Block.
* @return the x-coordinate of this Block.
*/
public double getX()
{
return xPos;
}
/**
* Method to return the y-coordinate of this Block.
* @return the y-coordinate of this Block.
*/
public double getY()
{
return yPos;
}
/**
* Method to get the left x-coordinate of this rotated Block.
* @return The x-coordinate of the left border of the rotated Block.
*/
public double getLeft()
{
if(o == Orientation.R || o == Orientation.RRR
|| o == Orientation.XR || o == Orientation.XRRR
|| o == Orientation.YR || o == Orientation.YRRR
|| o == Orientation.XYR || o == Orientation.XYRRR)
{
return xPos - halfHeight;
}
else
{
return xPos - halfWidth;
}
}
/**
* Method to get the top y-coordinate of this rotated Block.
* @return The y-coordinate of the top border of the rotated Block.
*/
public double getTop()
{
if(o == Orientation.R || o == Orientation.RRR
|| o == Orientation.XR || o == Orientation.XRRR
|| o == Orientation.YR || o == Orientation.YRRR
|| o == Orientation.XYR || o == Orientation.XYRRR)
{
return yPos + halfWidth;
}
else
{
return yPos + halfHeight;
}
}
/**
* Method to get the right x-coordinate of this rotated Block.
* @return The x-coordinate of the right border of the rotated Block.
*/
public double getRight()
{
if(o == Orientation.R || o == Orientation.RRR
|| o == Orientation.XR || o == Orientation.XRRR
|| o == Orientation.YR || o == Orientation.YRRR
|| o == Orientation.XYR || o == Orientation.XYRRR)
{
return xPos + halfHeight;
}
else
{
return xPos + halfWidth;
}
}
/**
* Method to get the bottom y-coordinate of this rotated Block.
* @return The y-coordinate of the bottom border of the rotated Block.
*/
public double getBottom()
{
if(o == Orientation.R || o == Orientation.RRR
|| o == Orientation.XR || o == Orientation.XRRR
|| o == Orientation.YR || o == Orientation.YRRR
|| o == Orientation.XYR || o == Orientation.XYRRR)
{
return yPos - halfWidth;
}
else
{
return yPos - halfHeight;
}
}
/**
* Method to check this Block for intersection with another.
* @param other The other Block to check this one for intersection with.
* @return Whether this Block intersects the other.
*/
public boolean intersects(Block other)
{
return ( other.getLeft() < getRight()
&& other.getRight() > getLeft()
&& other.getTop() > getBottom()
&& other.getBottom() < getTop() );
}
/**
* Method to calculate the intersection area with another Block.
* @param other The other block which possibly intersects this Block.
* @return The intersection area - 0.0 if empty.
*/
public double intersectionArea(Block other)
{
if (intersects(other))
{
double left = Math.max(getLeft(), other.getLeft());
double top = Math.min(getTop(), other.getTop());
double right = Math.min(getRight(), other.getRight());
double bottom = Math.max(getBottom(), other.getBottom());
return (top-bottom)*(right-left);
}
else return 0.0;
}
/**
* Method to set the location of this Block.
* @param x the X-coordinate of the center of this Block.
* @param y the Y-coordinate of the center of this Block.
*/
public void setPos(double x, double y)
{
xPos = x;
yPos = y;
}
/**
* Method to mutate this Block.
* @param rand The random number generator of the calling thread.
*/
public void disturb(double avgW, Random rand)
{
// random (gaussian) mutation of position
xPos += 1.0*avgW * rand.nextGaussian();
yPos += 1.0*avgW * rand.nextGaussian();
}
public void disturbToCenter(double avgW, Random rand)
{
// random mutation of position in direction of center
xPos = xPos *= rand.nextDouble();
yPos = yPos *= rand.nextDouble();
}
public void disturbOrientation(Random rand)
{
switch(rand.nextInt(16))
{
case 0:
o = Orientation.IDENT;
break;
case 1:
o = Orientation.R;
break;
case 2:
o = Orientation.RR;
break;
case 3:
o = Orientation.RRR;
break;
case 4:
o = Orientation.X;
break;
case 5:
o = Orientation.XR;
break;
case 6:
o = Orientation.XRR;
break;
case 7:
o = Orientation.XRRR;
break;
case 8:
o = Orientation.Y;
break;
case 9:
o = Orientation.YR;
break;
case 10:
o = Orientation.YRR;
break;
case 11:
o = Orientation.YRRR;
break;
case 12:
o = Orientation.XY;
break;
case 13:
o = Orientation.XYR;
break;
case 14:
o = Orientation.XYRR;
break;
case 15:
o = Orientation.XYRRR;
break;
}
}
}