/* * Copyright (C) 2014 Alfons Wirtz * website www.freerouting.net * * This program 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. * * This program 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 at <http://www.gnu.org/licenses/> * for more details. * * RatsNest.java * * Created on 18. Maerz 2004, 07:30 */ package interactive; import java.util.Collection; import java.util.LinkedList; import java.util.Iterator; import java.util.Vector; import java.awt.Graphics; import datastructures.UndoableObjects; import geometry.planar.FloatPoint; import rules.Net; import board.BasicBoard; import board.Item; import board.Connectable; import boardgraphics.GraphicsContext; /** * Creates all Incompletes (Ratsnest) to display them on the screen * * @author Alfons Wirtz */ public class RatsNest { /** Creates a new instance of RatsNest */ public RatsNest(BasicBoard p_board, java.util.Locale p_locale) { this.locale = p_locale; int max_net_no = p_board.rules.nets.max_net_no(); // Create the net item lists at once for performance reasons. Vector<Collection<Item>> net_item_lists = new Vector<Collection<Item>>(max_net_no); for (int i = 0; i < max_net_no; ++i) { net_item_lists.add(new LinkedList<Item>()); } Iterator<UndoableObjects.UndoableObjectNode> it = p_board.item_list.start_read_object(); for(;;) { Item curr_item = (Item)p_board.item_list.read_object(it); if (curr_item == null) { break; } if (curr_item instanceof Connectable) { for (int i = 0; i < curr_item.net_count(); ++i) { net_item_lists.get(curr_item.get_net_no(i) -1).add(curr_item); } } } this.net_incompletes = new NetIncompletes[max_net_no]; this.is_filtered = new boolean[max_net_no]; for (int i = 0; i < net_incompletes.length; ++i) { net_incompletes[i] = new NetIncompletes(i + 1, net_item_lists.get(i), p_board, p_locale); is_filtered[i] = false; } } /** * Recalculates the incomplete connections for the input net */ public void recalculate(int p_net_no, BasicBoard p_board) { if (p_net_no >= 1 && p_net_no <= net_incompletes.length) { Collection<Item> item_list = p_board.get_connectable_items(p_net_no); net_incompletes[p_net_no - 1] = new NetIncompletes(p_net_no, item_list, p_board, locale); } } /** * Recalculates the incomplete connections for the input net with the input item list. */ public void recalculate(int p_net_no, Collection<Item> p_item_list, BasicBoard p_board) { if (p_net_no >= 1 && p_net_no <= net_incompletes.length) { // copy p_item_list, because it will be changed inside the constructor of NetIncompletes Collection<Item> item_list = new LinkedList<Item>(p_item_list); net_incompletes[p_net_no - 1] = new NetIncompletes(p_net_no, item_list, p_board, locale); } } public int incomplete_count() { int result = 0; for (int i = 0; i < net_incompletes.length; ++i) { result += net_incompletes[i].count(); } return result; } public int incomplete_count(int p_net_no) { if (p_net_no <= 0 || p_net_no > net_incompletes.length) { return 0; } return net_incompletes[p_net_no - 1].count(); } public int length_violation_count() { int result = 0; for (int i = 0; i < net_incompletes.length; ++i) { if (net_incompletes[i].get_length_violation() != 0) { ++result; } } return result; } /** * Returns the length of the violation of the length restriction of the net with number p_net_no, * > 0, if the cumulative trace length is to big, * < 0, if the trace length is to smalll, * 0, if the thace length is ok or the net has no length restrictions */ public double get_length_violation(int p_net_no) { if (p_net_no <= 0 || p_net_no > net_incompletes.length) { return 0; } return net_incompletes[p_net_no - 1].get_length_violation(); } /** * Returns all airlines of the ratsnest. */ public AirLine [] get_airlines() { AirLine[] result = new AirLine[incomplete_count()]; int curr_index = 0; for (int i = 0; i < net_incompletes.length; ++i) { Collection<AirLine> curr_list = net_incompletes[i].incompletes; for (AirLine curr_line : curr_list) { result[curr_index] = curr_line; ++curr_index; } } return result; } public void hide() { hidden = true; } public void show() { hidden = false; } /** * Recalculate the length matching violations. * Return false, if the length violations have not changed. */ public boolean recalculate_length_violations() { boolean result = false; for (int i = 0; i < net_incompletes.length; ++i) { if (net_incompletes[i].calc_length_violation()) { result = true; } } return result; } /** * Used for example to hide the incompletes during interactive routiing. */ public boolean is_hidden() { return hidden; } /** * Sets the visibility filter for the incompletes of the input net. */ public void set_filter(int p_net_no, boolean p_value) { if (p_net_no < 1 || p_net_no > is_filtered.length) { return; } is_filtered[p_net_no - 1] = p_value; } public void draw(Graphics p_graphics, GraphicsContext p_graphics_context) { boolean draw_length_violations_only = this.hidden; for (int i = 0; i < net_incompletes.length; ++i) { if (!is_filtered[i]) { net_incompletes[i].draw(p_graphics, p_graphics_context, draw_length_violations_only); } } } private final NetIncompletes [] net_incompletes; private final boolean[] is_filtered; public boolean hidden = false; private final java.util.Locale locale; /** * Describes a single incomplete connection of the ratsnest. */ public static class AirLine implements Comparable<AirLine>, board.ObjectInfoPanel.Printable { AirLine(Net p_net, Item p_from_item, FloatPoint p_from_corner, Item p_to_item, FloatPoint p_to_corner, java.util.Locale p_locale) { net = p_net; from_item = p_from_item; from_corner = p_from_corner; to_item = p_to_item; to_corner = p_to_corner; this.locale = p_locale; } public int compareTo(AirLine p_other) { return this.net.name.compareTo(p_other.net.name); } public String toString() { String result = this.net.name + ": " + item_info(from_item) + " - " + item_info(to_item); return result; } private String item_info(Item p_item) { java.util.ResourceBundle resources = java.util.ResourceBundle.getBundle("interactive.resources.RatsNest", this.locale); String result; if (p_item instanceof board.Pin) { board.Pin curr_pin = (board.Pin) p_item; result = curr_pin.component_name() + ", " + curr_pin.name(); } else if (p_item instanceof board.Via) { result = resources.getString("via"); } else if (p_item instanceof board.Trace) { result = resources.getString("trace"); } else if (p_item instanceof board.ConductionArea) { result = resources.getString("conduction_area"); } else { result = resources.getString("unknown"); } return result; } public void print_info(board.ObjectInfoPanel p_window, java.util.Locale p_locale) { java.util.ResourceBundle resources = java.util.ResourceBundle.getBundle("interactive.resources.RatsNest", p_locale); p_window.append_bold(resources.getString("incomplete")); p_window.append(" " + resources.getString("net") + " "); p_window.append(net.name); p_window.append(" " + resources.getString("from") + " ", "Incomplete Start Item", from_item); p_window.append(from_corner); p_window.append(" " + resources.getString("to") + " ", "Incomplete End Item", to_item); p_window.append(to_corner); p_window.newline(); } public final Net net; public final Item from_item; public final FloatPoint from_corner; public final Item to_item; public final FloatPoint to_corner; private final java.util.Locale locale; } }