gboolean node_store_is_pin_at_pos (NodeStore *store, Coords pos) { int num_pins; Coords part_pos; GList *p; Part *part; Pin *pins; int i; gdouble x, y; for (p = store->parts; p; p = p->next) { part = PART (p->data); num_pins = part_get_num_pins (part); item_data_get_pos (ITEM_DATA (part), &part_pos); pins = part_get_pins (part); for (i = 0; i < num_pins; i++) { x = part_pos.x + pins[i].offset.x; y = part_pos.y + pins[i].offset.y; if (fabs (x - pos.x) < NODE_EPSILON && fabs (y - pos.y) < NODE_EPSILON) return TRUE; } } return FALSE; }
int node_store_is_pin_at_pos (NodeStore *store, SheetPos pos) { int num_pins; SheetPos part_pos; GList *p; Part *part; Pin *pins; int i; gdouble x, y; for (p = store->parts; p; p = p->next) { part = PART (p->data); num_pins = part_get_num_pins (part); item_data_get_pos (ITEM_DATA (part), &part_pos); pins = part_get_pins (part); for (i = 0; i < num_pins; i++) { x = part_pos.x + pins[i].offset.x; y = part_pos.y + pins[i].offset.y; if ((x == pos.x) && (y == pos.y)) { return 1; } } } g_list_free_full (p, g_object_unref); return 0; }
static GSList * wire_intersect_parts (NodeStore *store, Wire *wire) { GList *list; GSList *ip_list; Node *node; SheetPos lookup_pos; SheetPos part_pos, wire_pos, wire_length; Part *part; double x, y, wire_x1, wire_y1, wire_x2, wire_y2; int i, num_pins; g_return_val_if_fail (store != NULL, FALSE); g_return_val_if_fail (IS_NODE_STORE (store), FALSE); g_return_val_if_fail (wire != NULL, FALSE); g_return_val_if_fail (IS_WIRE (wire), FALSE); ip_list = NULL; wire_get_pos_and_length (wire, &wire_pos, &wire_length); wire_x1 = wire_pos.x; wire_x2 = wire_pos.x + wire_length.x; wire_y1 = wire_pos.y; wire_y2 = wire_pos.y + wire_length.y; // Go through all the parts and see which of their // pins that intersect the wire. for (list = store->parts; list; list = list->next) { part = list->data; num_pins = part_get_num_pins (part); item_data_get_pos (ITEM_DATA (part), &part_pos); for (i = 0; i < num_pins; i++) { Pin *pins; pins = part_get_pins (part); x = part_pos.x + pins[i].offset.x; y = part_pos.y + pins[i].offset.y; lookup_pos.x = x; lookup_pos.y = y; // If there is a wire at this pin's position, // add it to the return list. if (is_wire_at_pos (wire_x1, wire_y1, wire_x2, wire_y2, lookup_pos)) { node = node_store_get_node (store, lookup_pos); if (node != NULL) ip_list = g_slist_prepend (ip_list, node); } } } g_list_free_full (list, g_object_unref); return ip_list; }
int node_store_add_part (NodeStore *self, Part *part) { GSList *wire_list, *list; Node *node; SheetPos lookup_key; SheetPos part_pos; gdouble x, y; int i, num_pins; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (IS_NODE_STORE (self), FALSE); g_return_val_if_fail (part != NULL, FALSE); g_return_val_if_fail (IS_PART (part), FALSE); num_pins = part_get_num_pins (part); item_data_get_pos (ITEM_DATA (part), &part_pos); for (i = 0; i < num_pins; i++) { Pin *pins; pins = part_get_pins (part); x = part_pos.x + pins[i].offset.x; y = part_pos.y + pins[i].offset.y; //Use the position of the pin as hash key. lookup_key.x = x; lookup_key.y = y; // Retrieve a node for this position. node = node_store_get_or_create_node (self, lookup_key); // Add all the wires that intersect this pin to the node store. wire_list = wires_at_pos (self, lookup_key); for (list = wire_list; list; list = list->next) { Wire *wire = list->data; NG_DEBUG ("Add pin to wire.\n"); node_add_wire (node, wire); wire_add_node (wire, node); } g_slist_free (wire_list); node_add_pin (node, &pins[i]); } g_object_set (G_OBJECT (part), "store", self, NULL); self->parts = g_list_prepend (self->parts, part); self->items = g_list_prepend (self->items, part); return TRUE; }
int node_store_remove_part (NodeStore *self, Part *part) { Node *node; SheetPos lookup_key; SheetPos pos; gdouble x, y; int i, num_pins; Pin *pins; g_return_val_if_fail (self != NULL, FALSE); g_return_val_if_fail (IS_NODE_STORE (self), FALSE); g_return_val_if_fail (part != NULL, FALSE); g_return_val_if_fail (IS_PART (part), FALSE); self->parts = g_list_remove (self->parts, part); self->items = g_list_remove (self->items, part); num_pins = part_get_num_pins (part); item_data_get_pos (ITEM_DATA (part), &pos); pins = part_get_pins (part); for (i = 0; i < num_pins; i++) { x = pos.x + pins[i].offset.x; y = pos.y + pins[i].offset.y; // Use the position of the pin as lookup key. lookup_key.x = x; lookup_key.y = y; node = g_hash_table_lookup (self->nodes, &lookup_key); if (node) { if (!node_remove_pin (node, &pins[i])) { g_warning ("Couldn't remove pin."); return FALSE; } // If the node is empty after removing the pin, // remove the node as well. if (node_is_empty (node)) { g_hash_table_remove (self->nodes, &lookup_key); g_object_unref (G_OBJECT (node)); } } else { return FALSE; } } return TRUE; }
/** * register a part to the nodestore */ gboolean node_store_add_part (NodeStore *self, Part *part) { NG_DEBUG ("-0-"); g_return_val_if_fail (self, FALSE); g_return_val_if_fail (IS_NODE_STORE (self), FALSE); g_return_val_if_fail (part, FALSE); g_return_val_if_fail (IS_PART (part), FALSE); GSList *iter, *copy; Node *node; Coords pin_pos; Coords part_pos; int i, num_pins; Pin *pins; num_pins = part_get_num_pins (part); pins = part_get_pins (part); item_data_get_pos (ITEM_DATA (part), &part_pos); for (i = 0; i < num_pins; i++) { // Use the position of the pin as hash key. pin_pos.x = part_pos.x + pins[i].offset.x; pin_pos.y = part_pos.y + pins[i].offset.y; // Retrieve a node for this position. node = node_store_get_or_create_node (self, pin_pos); // Add all the wires that intersect this pin to the node store. copy = get_wires_at_pos (self, pin_pos); for (iter = copy; iter; iter = iter->next) { Wire *wire = copy->data; node_add_wire (node, wire); wire_add_node (wire, node); } g_slist_free (copy); node_add_pin (node, &pins[i]); } g_object_set (G_OBJECT (part), "store", self, NULL); self->parts = g_list_prepend (self->parts, part); self->items = g_list_prepend (self->items, part); return TRUE; }
/** * remove/unregister a part from the nodestore * this does _not_ free the part! */ gboolean node_store_remove_part (NodeStore *self, Part *part) { Node *node; Coords pin_pos; Coords part_pos; int i, num_pins; Pin *pins; g_return_val_if_fail (self, FALSE); g_return_val_if_fail (IS_NODE_STORE (self), FALSE); g_return_val_if_fail (part, FALSE); g_return_val_if_fail (IS_PART (part), FALSE); self->parts = g_list_remove (self->parts, part); self->items = g_list_remove (self->items, part); num_pins = part_get_num_pins (part); item_data_get_pos (ITEM_DATA (part), &part_pos); pins = part_get_pins (part); for (i = 0; i < num_pins; i++) { pin_pos.x = part_pos.x + pins[i].offset.x; pin_pos.y = part_pos.y + pins[i].offset.y; node = g_hash_table_lookup (self->nodes, &pin_pos); if (node) { if (!node_remove_pin (node, &pins[i])) { g_warning ("Could not remove pin[%i] from node %p.", i, node); return FALSE; } // If the node is empty after removing the pin, // remove the node as well. if (node_is_empty (node)) { g_hash_table_remove (self->nodes, &pin_pos); g_object_unref (G_OBJECT (node)); } } else { return FALSE; } } return TRUE; }
void part_item_update_node_label (PartItem *item) { PartItemPriv *priv; Part *part; GSList *labels; GooCanvasItem *canvas_item; Pin *pins; gint num_pins; g_return_if_fail (item != NULL); g_return_if_fail (IS_PART_ITEM (item)); priv = item->priv; part = PART (sheet_item_get_data (SHEET_ITEM (item))); g_return_if_fail (IS_PART (part) ); // Put the label of each node num_pins = part_get_num_pins (part); if (num_pins == 1) { pins = part_get_pins (part); labels = priv->label_nodes; for (labels = priv->label_nodes; labels; labels=labels->next) { char *txt; txt = g_strdup_printf ("V(%d)", pins[0].node_nr); canvas_item = labels->data; if (pins[0].node_nr != 0) g_object_set (canvas_item, "text", txt, "fill_color", LABEL_COLOR, "font", "Sans 8", NULL); else g_object_set (canvas_item, "text", "", NULL); g_free (txt); } } }
/** * add/register the wire to the nodestore * * @param store * @param wire * @returns TRUE if the wire was added or merged, else FALSE */ gboolean node_store_add_wire (NodeStore *store, Wire *wire) { GList *list; Node *node; int i = 0; g_return_val_if_fail (store, FALSE); g_return_val_if_fail (IS_NODE_STORE (store), FALSE); g_return_val_if_fail (wire, FALSE); g_return_val_if_fail (IS_WIRE (wire), FALSE); // Check for intersection with other wires. for (list = store->wires; list; list = list->next) { g_assert (list->data != NULL); g_assert (IS_WIRE (list->data)); Coords where = {-77.77, -77.77}; Wire *other = list->data; if (do_wires_intersect (wire, other, &where)) { if (is_t_crossing (wire, other, &where) || is_t_crossing (other, wire, &where)) { node = node_store_get_or_create_node (store, where); node_add_wire (node, wire); node_add_wire (node, other); wire_add_node (wire, node); wire_add_node (other, node); NG_DEBUG ("Add wire %p to wire %p @ %lf,%lf.\n", wire, other, where.x, where.y); } else { // magic node removal if a x crossing is overlapped with another wire node = node_store_get_node (store, where); NG_DEBUG ("Nuke that node [ %p ] at coords inbetween", node); if (node) { Coords c[4]; wire_get_start_and_end_pos (other, c + 0, c + 1); wire_get_start_and_end_pos (wire, c + 2, c + 3); if (!coords_equal (&where, c + 0) && !coords_equal (&where, c + 1) && !coords_equal (&where, c + 2) && !coords_equal (&where, c + 3)) { wire_remove_node (wire, node); wire_remove_node (other, node); node_remove_wire (node, wire); node_remove_wire (node, other); } } } } } // Check for overlapping with other wires. do { for (list = store->wires; list; list = list->next) { g_assert (list->data != NULL); g_assert (IS_WIRE (list->data)); Wire *other = list->data; Coords so, eo; const gboolean overlap = do_wires_overlap (wire, other, &so, &eo); NG_DEBUG ("overlap [ %p] and [ %p ] -- %s", wire, other, overlap == TRUE ? "YES" : "NO"); if (overlap) { Node *sn = node_store_get_node (store, eo); Node *en = node_store_get_node (store, so); #if 1 wire = vulcanize_wire (store, wire, other, &so, &eo); node_store_remove_wire (store, g_object_ref (other)); // equiv // wire_unregister // XXX FIXME this // modifies the list // we iterate over! // delay this until idle, so all handlers like adding view // representation are completed so existing wire-items can be deleted // properly // this is not fancy nor nice but seems to work fairly nicly g_idle_add (delayed_wire_delete, other); break; NG_DEBUG ("overlapping of %p with %p ", wire, other); #else if (!sn && !en) { wire = vulcanize_wire (store, wire, other, &so, &eo); } else if (!sn) { NG_DEBUG ("do_something(TM) : %p sn==NULL ", other); } else if (!en) { NG_DEBUG ("do_something(TM) : %p en==NULL ", other); } else { NG_DEBUG ("do_something(TM) : %p else ", other); } #endif } else { NG_DEBUG ("not of %p with %p ", wire, other); } } } while (list); // Check for intersection with parts (pins). for (list = store->parts; list; list = list->next) { g_assert (list->data != NULL); g_assert (IS_PART (list->data)); Coords part_pos; gint num_pins = -1; Part *part = list->data; num_pins = part_get_num_pins (part); item_data_get_pos (ITEM_DATA (part), &part_pos); // Go through all the parts and see which of their // pins that intersect the wire. for (i = 0; i < num_pins; i++) { Pin *pins; Coords lookup_pos; pins = part_get_pins (part); lookup_pos.x = part_pos.x + pins[i].offset.x; lookup_pos.y = part_pos.y + pins[i].offset.y; // If there is a wire at this pin's position, // add it to the return list. if (is_point_on_wire (wire, &lookup_pos)) { Node *node; node = node_store_get_node (store, lookup_pos); if (node != NULL) { // Add the wire to the node (pin) that it intersected. node_add_wire (node, wire); wire_add_node (wire, node); NG_DEBUG ("Add wire %p to pin (node) %p.\n", wire, node); } else { g_warning ("Bug: Found no node at pin at (%g %g).\n", lookup_pos.x, lookup_pos.y); } } } } g_object_set (G_OBJECT (wire), "store", store, NULL); store->wires = g_list_prepend (store->wires, wire); store->items = g_list_prepend (store->items, wire); return TRUE; }
static void create_canvas_label_nodes (PartItem *item, Part *part) { GooCanvasItem *canvas_item; GSList *item_list; GooCanvasItem *group; Pin *pins; int num_pins, i; Coords p1, p2; GooCanvasAnchorType anchor; g_return_if_fail (item != NULL); g_return_if_fail (IS_PART_ITEM (item)); g_return_if_fail (part != NULL); g_return_if_fail (IS_PART (part)); num_pins = part_get_num_pins (part); pins = part_get_pins (part); group = item->priv->node_group; item_list = NULL; get_cached_bounds (item, &p1, &p2); switch (part_get_rotation (part)) { case 0: anchor = GOO_CANVAS_ANCHOR_SOUTH_WEST; break; case 90: anchor = GOO_CANVAS_ANCHOR_NORTH_WEST; break; case 180: anchor = GOO_CANVAS_ANCHOR_NORTH_EAST; break; case 270: anchor = GOO_CANVAS_ANCHOR_SOUTH_EAST; break; default: anchor = GOO_CANVAS_ANCHOR_SOUTH_WEST; } for (i = 0; i < num_pins; i++) { int x, y; char *text; x = pins[i].offset.x; y = pins[i].offset.y; text = g_strdup_printf ("%d", pins[i].node_nr); canvas_item = goo_canvas_text_new (GOO_CANVAS_ITEM (group), text, (double) x, (double) y, 0, anchor, "fill_color", "black", "font", "Sans 8", NULL); // Shift slightly the label for a Voltmeter if (i == 0) goo_canvas_item_translate (canvas_item, -15.0, -10.0); item_list = g_slist_prepend (item_list, canvas_item); g_free (text); } item_list = g_slist_reverse (item_list); item->priv->label_nodes = item_list; }