All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.electric.database.geometry.PolyMerge Maven / Gradle / Ivy

/* -*- tab-width: 4 -*-
 *
 * Electric(tm) VLSI Design System
 *
 * File: PolyMerge.java
 *
 * Copyright (c) 2004, 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.database.geometry;

import com.sun.electric.technology.Layer;
import com.sun.electric.util.math.DBMath;
import com.sun.electric.util.math.FixpTransform;
import com.sun.electric.util.math.GenMath;
import com.sun.electric.util.math.MutableBoolean;

import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.List;

/**
 * This is the Polygon Merging facility.
 * 

* Initially, call:
* PolyMerge merge = new PolyMerge();
* The returned value is used in subsequent calls. *

* For every polygon, call:
* merge.addPolygon(layer, poly);
* where "layer" is a layer and "poly" is a polygon to be added. *

* You can also subtract a polygon by calling:
* merge.subtract(layer, poly);
*

* To combine two different merges, use:
* merge.addMerge(addmerge, trans)
* to add the merge information in "addmerge" (transformed by "trans") *

* At end of merging, call:
* merge.getMergedPoints(layer)
* for each layer, and it returns an array of PolyBases on that layer. */ public class PolyMerge extends GeometryHandler { /** * Method to create a new "merge" object. */ public PolyMerge() { } /** * Method to add a PolyBase to the merged collection. * @param key the layer that this PolyBase sits on. * @param value the PolyBase to merge. If value is only Shape type * then it would take the bounding box. This might not be precise enough!. */ public void add(Layer key, Object value) { Layer layer = key; PolyBase poly; if (value instanceof PolyBase) poly = (PolyBase)value; else if (value instanceof Shape) poly = new PolyBase(((Shape)value).getBounds2D()); else return; addPolygon(layer, poly); } /** * Method to add a Rectangle to the merged collection. * @param layer the layer that this Poly sits on. * @param rect the Rectangle to merge. */ public void addRectangle(Layer layer, Rectangle2D rect) { Area area = (Area)layers.get(layer); if (area == null) { area = new Area(); layers.put(layer, area); } // add "rect" to "area" Area additionalArea = new Area(rect); area.add(additionalArea); } /** * Method to add a PolyBase to the merged collection. * @param layer the layer that this Poly sits on. * @param poly the PolyBase to merge. */ public void addPolygon(Layer layer, PolyBase poly) { Area area = (Area)layers.get(layer); if (area == null) { area = new Area(); layers.put(layer, area); } // add "poly" to "area" // It can't add only rectangles otherwise it doesn't cover // serpentine transistors. Area additionalArea = new Area(poly); area.add(additionalArea); } /** * Method to subtract a PolyBase from the merged collection. * @param layer the layer that this PolyBase sits on. * @param poly the PolyBase to merge. */ public void subtract(Object layer, Object poly) { Area area = (Area)layers.get(layer); if (area == null) return; Area subtractArea = new Area((PolyBase)poly); area.subtract(subtractArea); } /** * Method to add another Merge to this one. * @param subMerge the other Merge to add in. * @param trans a transformation on the other Merge. */ public void addAll(GeometryHandler subMerge, FixpTransform trans) { PolyMerge other = (PolyMerge)subMerge; addMerge(other, trans); } /** * Method to add another Merge to this one. * @param other the other Merge to add in. * @param trans a transformation on the other Merge. */ public void addMerge(PolyMerge other, FixpTransform trans) { for(Layer subLayer : other.layers.keySet()) { Area subArea = (Area)other.layers.get(subLayer); Area area = (Area)layers.get(subLayer); if (area == null) { area = new Area(); layers.put(subLayer, area); } Area newArea = subArea.createTransformedArea(trans); area.add(newArea); } } /** * Method to add one Layer to another in this merge. * @param fromLayer the other Layer to add in. * @param toLayer the destination layer that will contain the union of itself and "fromLayer". */ public void addLayer(Layer fromLayer, Layer toLayer) { Area fromArea = (Area)layers.get(fromLayer); if (fromArea == null) return; Area toArea = (Area)layers.get(toLayer); if (toArea == null) { toArea = new Area(fromArea); layers.put(toLayer, toArea); return; } toArea.add(fromArea); } /** * Method to determine whether a polygon intersects a layer in the merge. * @param layer the layer to test. * @param poly the polygon to examine. * @return true if any part of the polygon exists in that layer. */ public boolean intersects(Layer layer, PolyBase poly) { Area layerArea = (Area)layers.get(layer); if (layerArea == null) return false; // simple calculation for manhattan polygon Rectangle2D box = poly.getBox(); if (box != null) { return layerArea.intersects(box); } // more complex calculation (not done yet) Area intersectArea = new Area(poly); intersectArea.intersect(layerArea); return !intersectArea.isEmpty(); } /** * Method to intersect two layers in this merge and produce a third. * @param sourceA the first Layer to intersect. * @param sourceB the second Layer to intersect. * @param dest the destination layer to place the intersection of the first two. * If there is no intersection, all geometry on this layer is cleared. */ public void intersectLayers(Layer sourceA, Layer sourceB, Layer dest) { Area destArea = null; Area sourceAreaA = (Area)layers.get(sourceA); if (sourceAreaA != null) { Area sourceAreaB = (Area)layers.get(sourceB); if (sourceAreaB != null) { destArea = new Area(sourceAreaA); destArea.intersect(sourceAreaB); if (destArea.isEmpty()) destArea = null; } } if (destArea == null) layers.remove(dest); else layers.put(dest, destArea); } /** * Method to subtract one layer from another and produce a third. * @param sourceA the first Layer. * @param sourceB the second Layer, which gets subtracted from the first. * @param dest the destination layer to place the sourceA - sourceB. * If there is nothing left, all geometry on the layer is cleared. */ public void subtractLayers(Layer sourceA, Layer sourceB, Layer dest) { Area destArea = null; Area sourceAreaA = (Area)layers.get(sourceA); if (sourceAreaA != null) { Area sourceAreaB = (Area)layers.get(sourceB); if (sourceAreaB != null) { destArea = new Area(sourceAreaA); destArea.subtract(sourceAreaB); if (destArea.isEmpty()) destArea = null; } } if (destArea == null) layers.remove(dest); else layers.put(dest, destArea); } /** * Method to subtract another Merge to this one. * @param other the other Merge to subtract. */ public void subtractMerge(PolyMerge other) { for(Layer subLayer : other.layers.keySet()) { Area area = (Area)layers.get(subLayer); if (area == null) continue; Area subArea = (Area)other.layers.get(subLayer); area.subtract(subArea); } } /** * Method to inset one layer by a given amount and create a second layer. * @param source the Layer to inset. * @param dest the destination layer to place the inset geometry. * @param amount the distance to inset the layer. */ public void insetLayer(Layer source, Layer dest, double amount) { Area sourceArea = (Area)layers.get(source); if (sourceArea == null) layers.remove(dest); else { layers.put(dest, sourceArea.clone()); if (amount == 0) return; List orig = getAreaPoints(sourceArea, source, true); for(PolyBase poly : orig) { PolyBase.Point [] points = poly.getPoints(); for(int i=0; i pointList = getAreaPoints(area, null, true); double totalArea = 0; for(PolyBase p : pointList) { totalArea += p.getArea(); } return totalArea; } /** * Method to determine whether a point exists in the merge. * @param layer the layer being tested. * @param pt the point being tested. * @return true if the point is inside of the merge on the given layer. */ public boolean contains(Layer layer, Point2D pt) { Area area = (Area)layers.get(layer); if (area == null) return false; return area.contains(pt); } public Collection getObjects(Object layer, boolean modified, boolean simple) { // Since simple is used, correct detection of loops must be guaranteed // outside. return getMergedPoints((Layer)layer, simple); } /** * Method to return list of Polys on a given Layer in this Merge. * @param layer the layer in question. * @param simple * @return the list of Polys that describes this Merge. */ public List getMergedPoints(Layer layer, boolean simple) { Area area = (Area)layers.get(layer); if (area == null) return null; return getAreaPoints(area, layer, simple); } /** * Method to return a list of polygons in this merge for a given layer. * @param area the Area object that describes the merge. * @param layer the desired Layer. * @param simple true for simple polygons, false to allow complex ones. * @return a List of PolyBase objects that describes the layer in the merge. */ public static List getAreaPoints(Area area, Layer layer, boolean simple) { return PolyBase.getPointsInArea(area, layer, simple, true); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy