Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.sun.electric.technology.BoundsBuilder Maven / Gradle / Ivy
/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: BoundsBuilder.java
*
* Copyright (c) 2003, 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.technology;
import com.sun.electric.database.CellBackup;
import com.sun.electric.database.ImmutableArcInst;
import com.sun.electric.database.geometry.EGraphics;
import com.sun.electric.database.geometry.EPoint;
import com.sun.electric.database.geometry.ERectangle;
import com.sun.electric.database.geometry.Poly;
import com.sun.electric.util.math.FixpCoord;
import com.sun.electric.util.math.GenMath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
/**
* A support class to build shapes of arcs and nodes.
*/
public class BoundsBuilder extends AbstractShapeBuilder {
private long fixpMinX, fixpMinY, fixpMaxX, fixpMaxY;
public BoundsBuilder(TechPool techPool) {
setup(techPool);
clear();
}
public BoundsBuilder(CellBackup cellBackup) {
setup(cellBackup, null, false, true, false, null);
clear();
}
public void clear() {
fixpMinX = fixpMinY = Long.MAX_VALUE;
fixpMaxX = fixpMaxY = Long.MIN_VALUE;
}
/**
* Generate bounds of this ImmutableArcInst in easy case.
* @param a ImmutableArcInst to examine.
* @param coords grid coords to fill.
* @return true if bounds were generated.
*/
public boolean genBoundsEasy(ImmutableArcInst a, long[] gridCoords) {
ArcProto protoType = getTechPool().getArcProto(a.protoId);
CellBackup.Memoization m = getMemoization();
if (m != null ? m.isHardArc(a.arcId) : !protoType.isEasyShape(a, false)) {
return false;
}
long gridExtendOverMin = a.getGridExtendOverMin();
long minLayerExtend = gridExtendOverMin + protoType.getMinLayerExtend().getGrid();
if (minLayerExtend == 0) {
assert protoType.getNumArcLayers() == 1;
long x1 = a.tailLocation.getGridX();
long y1 = a.tailLocation.getGridY();
long x2 = a.headLocation.getGridX();
long y2 = a.headLocation.getGridY();
if (x1 <= x2) {
gridCoords[0] = x1;
gridCoords[2] = x2;
} else {
gridCoords[0] = x2;
gridCoords[2] = x1;
}
if (y1 <= y2) {
gridCoords[1] = y1;
gridCoords[3] = y2;
} else {
gridCoords[1] = y2;
gridCoords[3] = y1;
}
} else {
boolean tailExtended, headExtended;
AbstractShapeBuilder.Shrinkage shrinkage = getShrinkage();
if (shrinkage == null) {
tailExtended = a.isTailExtended();
headExtended = a.isHeadExtended();
} else {
tailExtended = false;
if (a.isTailExtended()) {
short shrinkT = getShrinkage().get(a.tailNodeId);
if (shrinkT == AbstractShapeBuilder.Shrinkage.EXTEND_90) {
tailExtended = true;
} else if (shrinkT != AbstractShapeBuilder.Shrinkage.EXTEND_0) {
return false;
}
}
headExtended = false;
if (a.isHeadExtended()) {
short shrinkH = getShrinkage().get(a.headNodeId);
if (shrinkH == AbstractShapeBuilder.Shrinkage.EXTEND_90) {
headExtended = true;
} else if (shrinkH != AbstractShapeBuilder.Shrinkage.EXTEND_0) {
return false;
}
}
}
a.makeGridBox(gridCoords, tailExtended, headExtended, gridExtendOverMin + protoType.getMaxLayerExtend().getGrid());
}
return true;
}
public ERectangle makeBounds() {
if (fixpMinX <= fixpMaxX) {
long gridMinX = fixpMinX >> FixpCoord.FRACTION_BITS;
long gridMinY = fixpMinY >> FixpCoord.FRACTION_BITS;
long gridMaxX = -((-fixpMaxX) >> FixpCoord.FRACTION_BITS);
long gridMaxY = -((-fixpMaxY) >> FixpCoord.FRACTION_BITS);
return ERectangle.fromGrid(gridMinX, gridMinY, gridMaxX - gridMinX, gridMaxY - gridMinY);
} else {
return null;
}
}
public ERectangle makeBounds(EPoint anchor, ERectangle oldBounds) {
long gridMinX, gridMinY, gridMaxX, gridMaxY;
if (fixpMinX <= fixpMaxX) {
gridMinX = fixpMinX >> FixpCoord.FRACTION_BITS;
gridMinY = fixpMinY >> FixpCoord.FRACTION_BITS;
gridMaxX = -((-fixpMaxX) >> FixpCoord.FRACTION_BITS);
gridMaxY = -((-fixpMaxY) >> FixpCoord.FRACTION_BITS);
} else {
gridMinX = gridMaxX = anchor.getGridX();
gridMinY = gridMaxY = anchor.getGridX();
}
if (oldBounds != null
&& gridMinX == oldBounds.getGridMinX() && gridMinY == oldBounds.getGridMinY()
&& gridMaxX == oldBounds.getGridMaxX() && gridMaxY == oldBounds.getGridMaxY()) {
return oldBounds;
}
return ERectangle.fromGrid(gridMinX, gridMinY, gridMaxX - gridMinX, gridMaxY - gridMinY);
}
@Override
public void addPoly(int numPoints, Poly.Type style, Layer layer, EGraphics graphicsOverride, PrimitivePort pp) {
if (style == Poly.Type.CIRCLEARC || style == Poly.Type.THICKCIRCLEARC) {
Point2D.Double p0 = new Point2D.Double(coords[0], coords[1]);
Point2D.Double p1 = new Point2D.Double(coords[2], coords[3]);
Point2D.Double p2 = new Point2D.Double(coords[4], coords[5]);
Rectangle2D bounds = GenMath.arcBBox(p1, p2, p0);
if (bounds.getMinX() < fixpMinX) {
fixpMinX = (long) Math.rint(bounds.getMinX());
if (bounds.getMinX() < fixpMinX) {
fixpMinX--;
}
}
if (bounds.getMinY() < fixpMinY) {
fixpMinY = (long) Math.rint(bounds.getMinY());
if (bounds.getMinY() < fixpMinY) {
fixpMinY--;
}
}
if (bounds.getMaxX() > fixpMaxX) {
fixpMaxX = (long) Math.rint(bounds.getMaxX());
if (bounds.getMaxX() > fixpMaxX) {
fixpMaxX++;
}
}
if (bounds.getMaxY() > fixpMaxY) {
fixpMaxY = (long) Math.rint(bounds.getMaxY());
if (bounds.getMaxY() > fixpMaxY) {
fixpMaxY++;
}
}
return;
}
if (style == Poly.Type.CIRCLE || style == Poly.Type.THICKCIRCLE || style == Poly.Type.DISC) {
long fixpCX = coords[0];
long fixpCY = coords[1];
long radius;
if (fixpCX == coords[2]) {
radius = Math.abs(coords[3] - fixpCY);
} else if (fixpCY == coords[3]) {
radius = Math.abs(coords[2] - fixpCX);
} else {
radius = GenMath.ceilLong(Point2D.distance(fixpCX, fixpCY, coords[2], coords[3]));
}
fixpMinX = Math.min(fixpMinX, fixpCX - radius);
fixpMinY = Math.min(fixpMinY, fixpCY - radius);
fixpMaxX = Math.max(fixpMaxX, fixpCX + radius);
fixpMaxY = Math.max(fixpMaxY, fixpCY + radius);
return;
}
for (int i = 0; i < numPoints; i++) {
long x = coords[i * 2];
long y = coords[i * 2 + 1];
fixpMinX = Math.min(fixpMinX, x);
fixpMinY = Math.min(fixpMinY, y);
fixpMaxX = Math.max(fixpMaxX, x);
fixpMaxY = Math.max(fixpMaxY, y);
}
}
@Override
public void addBox(Layer layer) {
fixpMinX = Math.min(fixpMinX, coords[0]);
fixpMinY = Math.min(fixpMinY, coords[1]);
fixpMaxX = Math.max(fixpMaxX, coords[2]);
fixpMaxY = Math.max(fixpMaxY, coords[3]);
}
}