10 #include <acfutils/cairo_utils.h>
11 #include <acfutils/perf.h>
14 #include "libelec_types_impl.h"
16 #define PX(pos) (pos_scale * (pos))
18 #define COMP_INFO_BG_RGB 0.8, 0.8, 0.8
19 #define MAX_NAME_LEN 128
27 static void show_text_aligned(cairo_t *cr,
double x,
double y,
unsigned align,
28 const char *format, ...) PRINTF_ATTR(5);
31 make_comp_name(const
char *in_name,
char out_name[MAX_NAME_LEN])
38 strlcpy(out_name, in_name, MAX_NAME_LEN);
39 for (
unsigned i = 0, n = strlen(out_name); i < n; i++) {
40 if (out_name[i] ==
'_')
43 if (strncmp(out_name,
"CB ", 3) == 0)
44 memmove(out_name, &out_name[3], strlen(out_name) - 3 + 1);
46 if (n > 4 && strcmp(&out_name[n - 4],
" O P") == 0)
47 out_name[n - 2] =
'/';
51 get_srcs(
const elec_comp_t *comp, elec_comp_t *srcs[ELEC_MAX_SRCS])
56 mutex_enter(&((elec_comp_t *)comp)->rw_ro_lock);
57 memcpy(srcs, comp->srcs_ext, sizeof (*srcs) * ELEC_MAX_SRCS);
58 mutex_exit(&((elec_comp_t *)comp)->rw_ro_lock);
62 count_srcs(elec_comp_t *srcs[ELEC_MAX_SRCS])
66 for (
unsigned n_srcs = 0; n_srcs < ELEC_MAX_SRCS; n_srcs++) {
67 if (srcs[n_srcs] == NULL)
70 return (ELEC_MAX_SRCS);
74 show_text_aligned(cairo_t *cr,
double x,
double y,
unsigned align,
75 const char *format, ...)
77 cairo_text_extents_t te;
82 ASSERT(format != NULL);
84 str = vsprintf_alloc(format, ap);
87 cairo_text_extents(cr, str, &te);
90 cairo_move_to(cr, x - te.x_bearing,
91 y - te.height / 2 - te.y_bearing);
93 case TEXT_ALIGN_CENTER:
94 cairo_move_to(cr, x - te.width / 2 - te.x_bearing,
95 y - te.height / 2 - te.y_bearing);
97 case TEXT_ALIGN_RIGHT:
98 cairo_move_to(cr, x - te.width - te.x_bearing,
99 y - te.height / 2 - te.y_bearing);
102 cairo_show_text(cr, str);
108 tie_node_pos(
const elec_comp_t *tie,
unsigned i)
113 ASSERT3U(tie->info->type, ==,
ELEC_TIE);
114 ASSERT3U(i, <, tie->n_links);
115 ASSERT(tie->n_links != 0);
117 pos = tie->info->gui.pos;
118 if (tie->n_links == 2) {
120 return (VECT2(pos.x - 1, pos.y));
122 return (VECT2(pos.x + 1, pos.y));
123 }
else if (tie->n_links == 3) {
136 off = vect2_rot(off, tie->info->gui.rot);
137 return (vect2_add(pos, VECT2(off.x, -off.y)));
139 vect2_t off = vect2_rot(VECT2(0, 1), tie->info->gui.rot);
141 off = vect2_rot(off, i * (360.0 / tie->n_links));
142 return (vect2_add(pos, VECT2(off.x, -off.y)));
147 pick_closer(vect2_t ref, vect2_t a, vect2_t b)
149 double la = vect2_abs(vect2_sub(a, ref));
150 double lb = vect2_abs(vect2_sub(b, ref));
151 return (la <= lb ? a : b);
155 elec_comp_get_nearest_pos(
const elec_comp_t *comp, vect2_t *comp_pos,
156 vect2_t *bus_pos,
double bus_sz,
bool *align_vert)
160 ASSERT(comp != NULL);
161 ASSERT(comp_pos != NULL);
162 ASSERT(bus_pos != NULL);
163 ASSERT(align_vert != NULL);
165 pos = comp->info->gui.pos;
166 if (IS_NULL_VECT(comp->info->gui.pos))
169 *align_vert = (comp->info->type ==
ELEC_TRU ||
172 switch (comp->info->type) {
174 *comp_pos = VECT2(pos.x, pos.y - 0.2);
177 *comp_pos = pick_closer(*bus_pos, vect2_add(pos, VECT2(-1, 0)),
178 vect2_add(pos, VECT2(1, 0)));
181 *comp_pos = pick_closer(*bus_pos,
182 vect2_add(pos, VECT2(-2.5, 0)),
183 vect2_add(pos, VECT2(2.5, 0)));
186 vect2_t p = VECT2(1e9, 1e9);
188 for (
unsigned i = 0; i < comp->n_links; i++)
189 p = pick_closer(*bus_pos, p, tie_node_pos(comp, i));
194 *comp_pos = comp->info->gui.pos;
197 *bus_pos = VECT2(bus_pos->x, clamp(comp_pos->y,
198 bus_pos->y - bus_sz, bus_pos->y + bus_sz));
204 draw_src_path(cairo_t *cr, cairo_path_t *path,
const elec_comp_t *comp)
206 cairo_pattern_t *pat;
208 elec_comp_t *srcs[ELEC_MAX_SRCS];
212 ASSERT(path != NULL);
213 ASSERT(comp != NULL);
215 get_srcs(comp, srcs);
216 n_srcs = count_srcs(srcs);
222 color = srcs[0]->info->gui.color;
223 cairo_append_path(cr, path);
224 cairo_set_source_rgb(cr, color.x, color.y, color.z);
226 cairo_set_source_rgb(cr, 0, 0, 0);
229 pat = cairo_pattern_create_linear(0, 0, n_srcs * 8, n_srcs * 8);
230 cairo_pattern_set_extend(pat, CAIRO_EXTEND_REPEAT);
231 for (
unsigned i = 0; i < n_srcs; i++) {
232 vect3_t color = srcs[i]->info->gui.color;
233 double off1 = i / (double)n_srcs;
234 double off2 = (i + 1) / (
double)n_srcs;
235 cairo_pattern_add_color_stop_rgb(pat, off1,
236 color.x, color.y, color.z);
237 cairo_pattern_add_color_stop_rgb(pat, off2,
238 color.x, color.y, color.z);
240 cairo_append_path(cr, path);
241 cairo_set_source(cr, pat);
243 cairo_set_source_rgb(cr, 0, 0, 0);
244 cairo_pattern_destroy(pat);
247 cairo_path_destroy(path);
251 draw_bus_conns(cairo_t *cr,
double pos_scale,
const elec_comp_t *bus)
255 ASSERT3U(bus->info->type, ==,
ELEC_BUS);
257 if (IS_NULL_VECT(bus->info->gui.pos))
262 for (
unsigned i = 0; i < bus->n_links; i++) {
263 vect2_t bus_pos = bus->info->gui.pos;
265 const elec_comp_t *comp = bus->links[i].comp;
269 if (!elec_comp_get_nearest_pos(comp, &comp_pos, &bus_pos,
270 bus->info->gui.sz, &align_vert)) {
277 cairo_move_to(cr, PX(bus_pos.x), PX(bus_pos.y));
278 cairo_line_to(cr, PX(comp_pos.x), PX(bus_pos.y));
279 cairo_line_to(cr, PX(comp_pos.x), PX(comp_pos.y));
281 cairo_move_to(cr, PX(bus_pos.x), PX(bus_pos.y));
282 cairo_line_to(cr, PX(AVG(bus_pos.x, comp_pos.x)),
284 cairo_line_to(cr, PX(AVG(bus_pos.x, comp_pos.x)),
286 cairo_line_to(cr, PX(comp_pos.x), PX(comp_pos.y));
288 path = cairo_copy_path(cr);
289 cairo_set_line_width(cr, 3);
292 cairo_set_line_width(cr, 2);
293 draw_src_path(cr, path, bus);
297 if (!bus->info->gui.invis) {
298 if (bus->info->gui.sz != 0 && !bus->info->gui.virt) {
299 cairo_arc(cr, PX(bus_pos.x), PX(bus_pos.y),
300 PX(0.4), 0, DEG2RAD(360));
301 }
else if (bus->n_links > 2) {
302 cairo_arc(cr, PX(bus_pos.x), PX(bus_pos.y),
303 PX(0.25), 0, DEG2RAD(360));
315 char name[MAX_NAME_LEN];
318 ASSERT(info != NULL);
320 color = info->gui.color;
324 cairo_set_source_rgb(cr, color.x, color.y, color.z);
325 cairo_arc(cr, PX(pos.x), PX(pos.y), PX(1.2), 0, DEG2RAD(360));
328 cairo_set_line_width(cr, 2);
329 cairo_set_source_rgb(cr, 0, 0, 0);
330 cairo_arc(cr, PX(pos.x), PX(pos.y), PX(1.2), 0, DEG2RAD(360));
331 if (info->gen.freq != 0) {
332 cairo_move_to(cr, PX(pos.x - 0.9), PX(pos.y));
333 cairo_rel_curve_to(cr, PX(0.2), PX(-0.7),
334 PX(0.7), PX(-0.7), PX(0.9), 0);
335 cairo_rel_curve_to(cr, PX(0.2), PX(0.7),
336 PX(0.7), PX(0.7), PX(0.9), 0);
338 cairo_move_to(cr, PX(pos.x - 0.8), PX(pos.y - 0.2));
339 cairo_rel_line_to(cr, PX(1.6), 0);
340 cairo_move_to(cr, PX(pos.x - 0.8), PX(pos.y + 0.2));
341 cairo_rel_line_to(cr, PX(1.6), 0);
345 make_comp_name(info->name, name);
346 show_text_aligned(cr, PX(pos.x), PX(pos.y + 2), TEXT_ALIGN_CENTER,
351 draw_bus(cairo_t *cr,
double pos_scale,
const elec_comp_t *bus)
366 if (info->gui.sz != 0) {
369 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
371 cairo_set_line_width(cr, 10);
373 cairo_set_line_width(cr, 3);
374 cairo_move_to(cr, PX(pos.x), PX(pos.y - info->gui.sz));
375 cairo_rel_line_to(cr, 0, PX(2 * info->gui.sz));
376 path = cairo_copy_path(cr);
378 cairo_set_line_width(cr, !info->gui.virt ? 4 : 2);
379 draw_src_path(cr, path, bus);
380 cairo_set_line_width(cr, 2);
381 cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
384 if (info->gui.sz != 0 && !info->gui.virt) {
385 char name[MAX_NAME_LEN];
386 make_comp_name(info->name, name);
387 show_text_aligned(cr, PX(pos.x), PX(pos.y - info->gui.sz - 1),
388 TEXT_ALIGN_CENTER,
"%s", name);
393 draw_cb_icon(cairo_t *cr,
double pos_scale,
double font_sz, vect2_t pos,
394 bool fuse,
bool set,
bool triphase,
const char *comp_name,
395 vect3_t bg_color,
const elec_comp_t *comp)
399 char name[MAX_NAME_LEN];
402 ASSERT(comp_name != NULL);
403 ASSERT(comp != NULL);
405 make_comp_name(comp_name, name);
410 cairo_move_to(cr, PX(pos.x), PX(pos.y - (set ? 0.5 : 1)));
411 cairo_set_line_width(cr, 2);
412 cairo_rel_line_to(cr, 0, PX(-0.5));
413 cairo_rel_move_to(cr, PX(-0.4), 0);
414 cairo_rel_line_to(cr, PX(0.8), 0);
417 cairo_set_line_width(cr, 3);
418 cairo_arc(cr, PX(pos.x), PX(pos.y + (set ? 0.5 : 0)), PX(1.1),
419 DEG2RAD(215), DEG2RAD(-35));
421 cairo_set_line_width(cr, 3);
422 cairo_move_to(cr, PX(pos.x - 1), PX(pos.y));
423 cairo_rel_curve_to(cr, PX(0.2), PX(0.8), PX(0.8), PX(0.8),
425 cairo_rel_curve_to(cr, PX(0.2), PX(-0.8), PX(0.8), PX(-0.8),
428 path = cairo_copy_path(cr);
431 cairo_set_line_width(cr, 2);
432 draw_src_path(cr, path, comp);
436 cairo_set_source_rgb(cr, bg_color.x, bg_color.y, bg_color.z);
437 cairo_arc(cr, PX(pos.x), PX(pos.y), PX(0.3), 0, DEG2RAD(360));
441 cairo_set_source_rgb(cr, 1, 1, 1);
442 cairo_arc(cr, PX(pos.x - 1), PX(pos.y), PX(0.2), 0, DEG2RAD(360));
443 cairo_new_sub_path(cr);
444 cairo_arc(cr, PX(pos.x + 1), PX(pos.y), PX(0.2), 0, DEG2RAD(360));
446 cairo_set_source_rgb(cr, 0, 0, 0);
447 cairo_arc(cr, PX(pos.x - 1), PX(pos.y), PX(0.2), 0, DEG2RAD(360));
448 cairo_new_sub_path(cr);
449 cairo_arc(cr, PX(pos.x + 1), PX(pos.y), PX(0.2), 0, DEG2RAD(360));
453 cairo_set_font_size(cr, round(0.75 * font_sz));
454 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_CENTER,
456 cairo_set_font_size(cr, font_sz);
459 text_y_off = (fuse ? 1.5 : 0.8);
460 show_text_aligned(cr, PX(pos.x), PX(pos.y + text_y_off),
461 TEXT_ALIGN_CENTER,
"%s", name);
465 draw_cb(cairo_t *cr,
double pos_scale,
const elec_comp_t *cb,
double font_sz,
470 draw_cb_icon(cr, pos_scale, font_sz, cb->info->gui.pos,
471 cb->info->cb.fuse, !cb->ro.failed && cb->scb.cur_set,
472 cb->info->cb.triphase, cb->info->name, bg_color, cb);
476 draw_shunt(cairo_t *cr,
double pos_scale,
const elec_comp_t *shunt)
481 char name[MAX_NAME_LEN];
484 ASSERT(shunt != NULL);
489 cairo_set_line_width(cr, 3);
490 cairo_move_to(cr, PX(pos.x - 2.5), PX(pos.y));
491 cairo_rel_line_to(cr, PX(1), PX(0));
492 for (
int i = 0; i < 3; i++) {
493 cairo_rel_line_to(cr, PX(0.25), PX(-0.7));
494 cairo_rel_line_to(cr, PX(0.5), PX(1.4));
495 cairo_rel_line_to(cr, PX(0.25), PX(-0.7));
497 cairo_rel_line_to(cr, PX(1), PX(0));
498 path = cairo_copy_path(cr);
501 cairo_set_line_width(cr, 2);
502 draw_src_path(cr, path, shunt);
504 make_comp_name(info->name, name);
505 show_text_aligned(cr, PX(pos.x), PX(pos.y + 1.7),
506 TEXT_ALIGN_CENTER,
"%s", name);
514 char name[MAX_NAME_LEN];
517 ASSERT(info != NULL);
519 color = info->gui.color;
524 cairo_set_source_rgb(cr, color.x, color.y, color.z);
525 cairo_rectangle(cr, PX(pos.x - 1.5), PX(pos.y - 1.5), PX(3), PX(3));
529 cairo_set_source_rgb(cr, 0, 0, 0);
531 cairo_rectangle(cr, PX(pos.x - 1.5), PX(pos.y - 1.5), PX(3), PX(3));
534 cairo_move_to(cr, PX(pos.x - 1.5), PX(pos.y + 1.5));
535 cairo_rel_line_to(cr, PX(3), PX(-3));
539 cairo_move_to(cr, PX(pos.x - 0.8), PX(pos.y - 1));
541 cairo_move_to(cr, PX(pos.x + 0.8), PX(pos.y + 1));
542 cairo_rel_move_to(cr, PX(-0.5), 0);
543 cairo_rel_curve_to(cr, PX(0.1), PX(-0.4),
544 PX(0.4), PX(-0.4), PX(0.5), 0);
545 cairo_rel_curve_to(cr, PX(0.1), PX(0.4),
546 PX(0.4), PX(0.4), PX(0.5), 0);
550 cairo_move_to(cr, PX(pos.x + 0.8), PX(pos.y + 1));
552 cairo_move_to(cr, PX(pos.x - 0.8), PX(pos.y - 1));
553 cairo_rel_move_to(cr, PX(-0.5), 0);
554 cairo_rel_line_to(cr, PX(1), 0);
558 make_comp_name(info->name, name);
559 show_text_aligned(cr, PX(pos.x - 2), PX(pos.y),
560 TEXT_ALIGN_RIGHT,
"%s", name);
568 char name[MAX_NAME_LEN];
571 ASSERT(info != NULL);
573 color = info->gui.color;
578 cairo_set_source_rgb(cr, color.x, color.y, color.z);
579 cairo_rectangle(cr, PX(pos.x - 1.5), PX(pos.y - 1.5), PX(3), PX(3));
583 cairo_set_source_rgb(cr, 0, 0, 0);
585 cairo_rectangle(cr, PX(pos.x - 1.5), PX(pos.y - 1.5), PX(3), PX(3));
588 cairo_move_to(cr, PX(pos.x - 1.5), PX(pos.y + 1.5));
589 cairo_rel_line_to(cr, PX(3), PX(-3));
592 cairo_move_to(cr, PX(pos.x - 0.8), PX(pos.y - 1));
593 cairo_rel_move_to(cr, PX(-0.5), 0);
594 cairo_rel_curve_to(cr, PX(0.1), PX(-0.4),
595 PX(0.4), PX(-0.4), PX(0.5), 0);
596 cairo_rel_curve_to(cr, PX(0.1), PX(0.4),
597 PX(0.4), PX(0.4), PX(0.5), 0);
599 cairo_move_to(cr, PX(pos.x + 0.8), PX(pos.y + 1));
600 cairo_rel_move_to(cr, PX(-0.5), 0);
601 cairo_rel_curve_to(cr, PX(0.1), PX(-0.4),
602 PX(0.4), PX(-0.4), PX(0.5), 0);
603 cairo_rel_curve_to(cr, PX(0.1), PX(0.4),
604 PX(0.4), PX(0.4), PX(0.5), 0);
608 make_comp_name(info->name, name);
609 show_text_aligned(cr, PX(pos.x - 2), PX(pos.y),
610 TEXT_ALIGN_RIGHT,
"%s", name);
614 draw_node(cairo_t *cr,
double pos_scale, vect2_t pos)
618 cairo_set_source_rgb(cr, 1, 1, 1);
619 cairo_arc(cr, PX(pos.x), PX(pos.y), PX(0.2), 0, DEG2RAD(360));
622 cairo_set_source_rgb(cr, 0, 0, 0);
623 cairo_arc(cr, PX(pos.x), PX(pos.y), PX(0.2), 0, DEG2RAD(360));
628 draw_tie(cairo_t *cr,
double pos_scale,
const elec_comp_t *tie)
630 vect2_t endpt[2] = { NULL_VECT2, NULL_VECT2 };
632 char name[MAX_NAME_LEN];
636 pos = tie->info->gui.pos;
640 cairo_set_line_width(cr, 4);
641 for (
unsigned i = 0; i < tie->n_links; i++) {
642 elec_comp_t *remote_bus = tie->links[i].comp;
643 vect2_t conn = VECT2(1e9, 1e9);
645 if (!tie->tie.cur_state[i])
648 for (
unsigned j = 0; j < tie->n_links; j++) {
649 conn = pick_closer(remote_bus->info->gui.pos, conn,
650 tie_node_pos(tie, j));
652 if (IS_NULL_VECT(endpt[0])) {
659 if (!IS_NULL_VECT(endpt[0]) && !IS_NULL_VECT(endpt[1])) {
662 cairo_move_to(cr, PX(endpt[0].x), PX(endpt[0].y));
663 cairo_line_to(cr, PX(endpt[1].x), PX(endpt[1].y));
664 path = cairo_copy_path(cr);
666 cairo_set_line_width(cr, 2);
667 draw_src_path(cr, path, tie);
670 if (tie->n_links == 2) {
671 cairo_move_to(cr, PX(pos.x - 1), PX(pos.y - 1));
672 cairo_rel_line_to(cr, PX(2), 0);
674 vect2_t node_pos = tie_node_pos(tie, 0);
675 vect2_t line = vect2_rot(VECT2(0, -2),
677 cairo_move_to(cr, PX(node_pos.x), PX(node_pos.y));
678 cairo_rel_line_to(cr, PX(line.x), PX(-line.y));
682 cairo_set_line_width(cr, 2);
683 for (
unsigned i = 0; i < tie->n_links; i++)
684 draw_node(cr, pos_scale, tie_node_pos(tie, i));
686 make_comp_name(tie->info->name, name);
687 if (tie->n_links == 3) {
688 show_text_aligned(cr, PX(pos.x), PX(pos.y + 1.8),
689 TEXT_ALIGN_CENTER,
"%s", name);
691 show_text_aligned(cr, PX(pos.x), PX(pos.y + 1.5),
692 TEXT_ALIGN_CENTER,
"%s", name);
697 draw_diode(cairo_t *cr,
double pos_scale,
const elec_comp_t *diode,
701 char name[MAX_NAME_LEN];
704 ASSERT(diode != NULL);
705 pos = diode->info->gui.pos;
708 cairo_translate(cr, PX(pos.x), PX(pos.y));
709 cairo_rotate(cr, DEG2RAD(diode->info->gui.rot));
710 cairo_move_to(cr, PX(0.4), 0);
711 cairo_rel_line_to(cr, PX(-1.3), PX(-0.8));
712 cairo_rel_line_to(cr, 0, PX(1.6));
714 cairo_set_line_width(cr, 4);
715 cairo_move_to(cr, PX(0.5), PX(-0.8));
716 cairo_rel_line_to(cr, 0, PX(1.6));
718 cairo_move_to(cr, PX(-2), 0);
719 cairo_rel_line_to(cr, PX(4), 0);
724 make_comp_name(diode->info->name, name);
725 show_text_aligned(cr, PX(pos.x), PX(pos.y + 1.5),
726 TEXT_ALIGN_CENTER,
"%s", name);
730 draw_load(cairo_t *cr,
double pos_scale,
double font_sz,
734 char name[MAX_NAME_LEN];
737 ASSERT(info != NULL);
741 switch (info->gui.load_type) {
742 case GUI_LOAD_GENERIC:
743 cairo_set_source_rgb(cr, 1, 1, 1);
744 cairo_rectangle(cr, PX(pos.x - 1), PX(pos.y - 1), PX(2), PX(2));
746 cairo_set_source_rgb(cr, 0, 0, 0);
747 cairo_rectangle(cr, PX(pos.x - 1), PX(pos.y - 1), PX(2), PX(2));
751 cairo_set_source_rgb(cr, 1, 1, 1);
752 cairo_arc(cr, PX(pos.x), PX(pos.y), PX(1), 0, DEG2RAD(360));
754 cairo_set_source_rgb(cr, 0, 0, 0);
755 cairo_arc(cr, PX(pos.x), PX(pos.y), PX(1), 0, DEG2RAD(360));
757 cairo_set_font_size(cr, 2 * font_sz);
758 show_text_aligned(cr, PX(pos.x), PX(pos.y),
759 TEXT_ALIGN_CENTER,
"M");
760 cairo_set_font_size(cr, font_sz);
764 make_comp_name(info->name, name);
765 show_text_aligned(cr, PX(pos.x), PX(pos.y + 1.7),
766 TEXT_ALIGN_CENTER,
"%s", name);
775 char name[MAX_NAME_LEN];
778 ASSERT(info != NULL);
780 color = info->gui.color;
784 cairo_set_source_rgb(cr, color.x, color.y, color.z);
785 cairo_arc(cr, PX(pos.x), PX(pos.y), PX(1.2), 0, DEG2RAD(360));
788 cairo_set_source_rgb(cr, 0, 0, 0);
789 cairo_arc(cr, PX(pos.x), PX(pos.y), PX(1.2), 0, DEG2RAD(360));
790 cairo_move_to(cr, PX(pos.x), PX(pos.y - 0.2));
791 cairo_rel_line_to(cr, 0, PX(-1.0));
794 cairo_move_to(cr, PX(pos.x + 0.4), PX(pos.y - 0.6));
795 cairo_rel_line_to(cr, PX(0.4), 0);
796 cairo_move_to(cr, PX(pos.x + 0.6), PX(pos.y - 0.8));
797 cairo_rel_line_to(cr, 0, PX(0.4));
799 cairo_move_to(cr, PX(pos.x - 1), PX(pos.y - 0.2));
800 cairo_rel_line_to(cr, PX(2), PX(0));
801 cairo_move_to(cr, PX(pos.x - 0.6), PX(pos.y + 0.2));
802 cairo_rel_line_to(cr, PX(1.2), PX(0));
805 cairo_move_to(cr, PX(pos.x), PX(pos.y + 0.2));
806 cairo_rel_line_to(cr, 0, PX(2.3));
807 cairo_move_to(cr, PX(pos.x - 1), PX(pos.y + 2.5));
808 cairo_rel_line_to(cr, PX(2), PX(0));
809 cairo_move_to(cr, PX(pos.x - 0.7), PX(pos.y + 2.9));
810 cairo_rel_line_to(cr, PX(1.4), PX(0));
811 cairo_move_to(cr, PX(pos.x - 0.4), PX(pos.y + 3.3));
812 cairo_rel_line_to(cr, PX(0.8), PX(0));
814 cairo_move_to(cr, PX(pos.x), PX(pos.y + 0.2));
815 cairo_rel_line_to(cr, 0, PX(1));
820 make_comp_name(info->name, name);
821 show_text_aligned(cr, PX(pos.x - 1.4), PX(pos.y),
822 TEXT_ALIGN_RIGHT,
"%s", name);
826 draw_label_box(cairo_t *cr,
double pos_scale,
double font_sz,
829 cairo_text_extents_t te;
832 double dash[2] = { PX(1), PX(0.5) };
833 char name[MAX_NAME_LEN];
836 ASSERT(info != NULL);
841 cairo_set_font_size(cr, font_sz * info->label_box.font_scale);
843 make_comp_name(info->name, name);
844 cairo_text_extents(cr, name, &te);
845 pos = info->label_box.pos;
846 sz = info->label_box.sz;
847 color = info->gui.color;
849 cairo_set_dash(cr, dash, 2, 0);
851 cairo_set_source_rgb(cr, color.x, color.y, color.z);
852 cairo_rectangle(cr, PX(pos.x), PX(pos.y), PX(sz.x), PX(sz.y));
859 cairo_set_source_rgb(cr, 0, 0, 0);
860 cairo_set_dash(cr, NULL, 0, 0);
861 cairo_rectangle(cr, PX(pos.x + sz.x / 2) - te.width / 2 - te.height / 2,
862 PX(pos.y) - te.height * 0.75, te.width + te.height,
868 cairo_set_source_rgb(cr, 1, 1, 1);
869 cairo_rectangle(cr, PX(pos.x + sz.x / 2) - te.width / 2 - te.height / 2,
870 PX(pos.y) - te.height * 0.75, te.width + te.height,
874 cairo_set_source_rgb(cr, 0, 0, 0);
875 cairo_move_to(cr, PX(pos.x + sz.x / 2) - te.width / 2,
876 PX(pos.y) - te.height / 2 - te.y_bearing);
877 cairo_show_text(cr, name);
904 cairo_set_source_rgb(cr, 0, 0, 0);
905 cairo_set_font_size(cr, font_sz);
906 cairo_set_line_width(cr, 2);
909 for (elec_comp_t *comp = list_head(&sys->comps); comp != NULL;
910 comp = list_next(&sys->comps, comp)) {
913 ASSERT(info != NULL);
915 draw_bus_conns(cr, pos_scale, comp);
918 for (elec_comp_t *comp = list_head(&sys->comps); comp != NULL;
919 comp = list_next(&sys->comps, comp)) {
922 ASSERT(info != NULL);
923 if (IS_NULL_VECT(info->gui.pos) || info->gui.invis)
926 switch (info->type) {
928 draw_bus(cr, pos_scale, comp);
931 draw_gen(cr, pos_scale, info);
934 draw_cb(cr, pos_scale, comp, font_sz, VECT3(1, 1, 1));
937 draw_shunt(cr, pos_scale, comp);
941 draw_tru_inv(cr, pos_scale, info);
944 draw_xfrmr(cr, pos_scale, info);
947 draw_tie(cr, pos_scale, comp);
950 draw_diode(cr, pos_scale, comp,
false);
953 draw_load(cr, pos_scale, font_sz, info);
956 draw_batt(cr, pos_scale, info,
true);
963 for (
size_t i = 0; i < sys->num_infos; i++) {
967 draw_label_box(cr, pos_scale, font_sz, info);
972 draw_comp_bg(cairo_t *cr,
double pos_scale, vect2_t pos, vect2_t sz)
978 cairo_utils_rounded_rect(cr, PX(pos.x - sz.x / 2),
979 PX(pos.y - sz.y / 2), PX(sz.x), PX(sz.y), PX(0.5));
980 path = cairo_copy_path(cr);
981 cairo_set_source_rgb(cr, COMP_INFO_BG_RGB);
984 cairo_append_path(cr, path);
985 cairo_set_source_rgb(cr, 0, 0, 0);
988 cairo_path_destroy(path);
992 draw_in_out_suffixes(cairo_t *cr,
double pos_scale, vect2_t pos,
993 unsigned num_in,
unsigned num_out)
997 for (
unsigned i = 0; i < num_in + num_out; i++) {
998 show_text_aligned(cr, PX(pos.x + 0.5),
999 PX(pos.y + (i + 0.25) * LINE_HEIGHT),
1000 TEXT_ALIGN_LEFT, i < num_in ?
"IN" :
"OUT");
1005 draw_comp_info(
const elec_comp_t *comp, cairo_t *cr,
double pos_scale,
1006 double font_sz, vect2_t pos)
1009 double U_in, I_in, W_in, U_out, I_out, W_out, f;
1010 elec_comp_t *srcs[ELEC_MAX_SRCS];
1013 ASSERT(comp != NULL);
1027 get_srcs(comp, srcs);
1028 n_srcs = count_srcs(srcs);
1030 if (comp->info->type !=
ELEC_GEN) {
1031 char name[MAX_NAME_LEN];
1032 const char *powered_by;
1036 powered_by =
"nothing";
1039 make_comp_name(srcs[0]->info->name, name);
1043 powered_by =
"(multiple)";
1046 show_text_aligned(cr, PX(pos.x), PX(pos.y),
1047 TEXT_ALIGN_LEFT,
"Powered by: %s", powered_by);
1048 pos.y += LINE_HEIGHT;
1051 switch (comp->info->type) {
1056 cairo_set_font_size(cr, 0.75 * font_sz);
1058 draw_in_out_suffixes(cr, pos_scale, pos, 3, 4);
1059 else if (comp->info->type ==
ELEC_TRU)
1060 draw_in_out_suffixes(cr, pos_scale, pos, 4, 3);
1062 draw_in_out_suffixes(cr, pos_scale, pos, 3, 3);
1064 cairo_set_font_size(cr, font_sz);
1065 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1066 "U : %.*fV", fixed_decimals(U_in, 4), U_in);
1067 pos.y += LINE_HEIGHT;
1068 if (comp->info->type !=
ELEC_INV && ac) {
1069 show_text_aligned(cr, PX(pos.x), PX(pos.y),
1070 TEXT_ALIGN_LEFT,
"f : %.*fHz",
1071 fixed_decimals(f, 4), f);
1072 pos.y += LINE_HEIGHT;
1074 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1075 "I : %.*fA", fixed_decimals(I_in, 4), I_in);
1076 pos.y += LINE_HEIGHT;
1077 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1078 "W : %.*fW", fixed_decimals(W_in, 4), W_in);
1079 pos.y += LINE_HEIGHT;
1080 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1081 "U : %.*fV", fixed_decimals(U_out, 4), U_out);
1082 pos.y += LINE_HEIGHT;
1083 if (comp->info->type ==
ELEC_INV) {
1084 show_text_aligned(cr, PX(pos.x), PX(pos.y),
1085 TEXT_ALIGN_LEFT,
"f : %.*fHz",
1086 fixed_decimals(f, 4), f);
1087 pos.y += LINE_HEIGHT;
1089 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1090 "I : %.*fA", fixed_decimals(I_out, 4), I_out);
1091 pos.y += LINE_HEIGHT;
1092 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1093 "W : %.*fW", fixed_decimals(W_out, 4), W_out);
1094 pos.y += LINE_HEIGHT;
1097 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1098 "U: %.*fV", fixed_decimals(U_out, 4), U_out);
1099 pos.y += LINE_HEIGHT;
1101 show_text_aligned(cr, PX(pos.x), PX(pos.y),
1102 TEXT_ALIGN_LEFT,
"f: %.*fHz",
1103 fixed_decimals(f, 4), f);
1104 pos.y += LINE_HEIGHT;
1106 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1107 "I: %.*fA", fixed_decimals(I_out, 4), I_out);
1108 pos.y += LINE_HEIGHT;
1109 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1110 "W: %.*fW", fixed_decimals(W_out, 4), W_out);
1118 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1119 "U: %.*fV", fixed_decimals(U_in, 4), U_in);
1120 pos.y += LINE_HEIGHT;
1122 show_text_aligned(cr, PX(pos.x), PX(pos.y),
1123 TEXT_ALIGN_LEFT,
"f: %.*fHz",
1124 fixed_decimals(f, 4), f);
1125 pos.y += LINE_HEIGHT;
1127 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1128 "I: %.*fA", fixed_decimals(I_in, 4), I_in);
1129 pos.y += LINE_HEIGHT;
1130 show_text_aligned(cr, PX(pos.x), PX(pos.y), TEXT_ALIGN_LEFT,
1131 "W: %.*fW", fixed_decimals(W_in, 4), W_in);
1139 draw_diode_info(
const elec_comp_t *diode, cairo_t *cr,
double pos_scale,
1140 double font_sz, vect2_t pos)
1142 const double TEXT_OFF_X = -6.5, TEXT_OFF_Y = 2.5;
1144 ASSERT(diode != NULL);
1145 ASSERT(diode->info != NULL);
1148 draw_comp_bg(cr, pos_scale, VECT2(pos.x, pos.y + 3), VECT2(14, 10));
1150 draw_diode(cr, pos_scale, diode,
true);
1151 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(pos.y + TEXT_OFF_Y),
1152 TEXT_ALIGN_LEFT,
"Type: Diode");
1153 draw_comp_info(diode, cr, pos_scale, font_sz,
1154 VECT2(pos.x + TEXT_OFF_X, pos.y + TEXT_OFF_Y + LINE_HEIGHT));
1158 draw_scb_info(
const elec_comp_t *cb, cairo_t *cr,
double pos_scale,
1159 double font_sz, vect2_t pos)
1161 const double TEXT_OFF_X = -6.5, TEXT_OFF_Y = 2.5;
1163 double y, height, box_y_off;
1166 ASSERT(cb->info != NULL);
1169 height = (cb->info->type ==
ELEC_CB ? 14 : 12);
1170 box_y_off = (cb->info->type ==
ELEC_CB ? 5 : 4);
1171 draw_comp_bg(cr, pos_scale, VECT2(pos.x, pos.y + box_y_off),
1174 if (cb->info->type ==
ELEC_CB) {
1175 draw_cb(cr, pos_scale, cb, font_sz,
1176 (vect3_t){COMP_INFO_BG_RGB});
1178 draw_shunt(cr, pos_scale, cb);
1181 y = pos.y + TEXT_OFF_Y;
1184 if (cb->info->type ==
ELEC_CB) {
1185 type = (cb->info->cb.fuse ?
"Fuse" :
"Circuit Breaker");
1187 type =
"Shunt Resistor";
1189 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y),
1190 TEXT_ALIGN_LEFT,
"Type: %s%s",
1191 cb->info->cb.triphase ?
"3-Phase " :
"", type);
1193 if (cb->info->type ==
ELEC_CB) {
1194 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y),
1195 TEXT_ALIGN_LEFT,
"State: %s",
1198 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y),
1199 TEXT_ALIGN_LEFT,
"Limit: %s%.*fA",
1200 cb->info->cb.triphase ?
"3 x " :
"",
1201 fixed_decimals(cb->info->cb.max_amps, 2),
1202 cb->info->cb.max_amps);
1204 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y),
1205 TEXT_ALIGN_LEFT,
"Location: %s", cb->info->location);
1208 draw_comp_info(cb, cr, pos_scale, font_sz,
1209 VECT2(pos.x + TEXT_OFF_X, y));
1213 draw_gen_info(
const elec_comp_t *gen, cairo_t *cr,
double pos_scale,
1214 double font_sz, vect2_t pos)
1216 const double TEXT_OFF_X = -6.5, TEXT_OFF_Y = 3;
1219 ASSERT(gen != NULL);
1220 ASSERT(gen->info != NULL);
1221 ASSERT3U(gen->info->type, ==,
ELEC_GEN);
1223 draw_comp_bg(cr, pos_scale, VECT2(pos.x, pos.y + 4), VECT2(14, 12));
1224 draw_gen(cr, pos_scale, gen->info);
1226 y = pos.y + TEXT_OFF_Y;
1228 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1229 "Type: %s Generator", gen->info->gen.freq != 0 ?
"AC" :
"DC");
1232 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1233 "RPM: %.0f", gen->gen.rpm);
1236 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1237 "Efficiency: %.1f%%", gen->gen.eff * 100);
1240 draw_comp_info(gen, cr, pos_scale, font_sz,
1241 VECT2(pos.x + TEXT_OFF_X, y));
1247 ASSERT(info != NULL);
1249 return (
"Inverter");
1250 if (info->tru.charger)
1251 return (
"Battery Charger");
1252 return (
"Transformer-Rectifier");
1256 draw_tru_inv_info(
const elec_comp_t *tru, cairo_t *cr,
double pos_scale,
1257 double font_sz, vect2_t pos)
1259 const double TEXT_OFF_X = -8.5, TEXT_OFF_Y = 3;
1262 ASSERT(tru != NULL);
1263 ASSERT(tru->info != NULL);
1266 draw_comp_bg(cr, pos_scale, VECT2(pos.x - 2, pos.y + 5.5),
1268 draw_tru_inv(cr, pos_scale, tru->info);
1270 y = pos.y + TEXT_OFF_Y;
1272 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1273 "Type: %s", tru_inv2str(tru->info));
1276 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1277 "Efficiency: %.1f%%", tru->tru.eff * 100);
1280 draw_comp_info(tru, cr, pos_scale, font_sz,
1281 VECT2(pos.x + TEXT_OFF_X, y));
1285 draw_xfrmr_info(
const elec_comp_t *xfrmr, cairo_t *cr,
double pos_scale,
1286 double font_sz, vect2_t pos)
1288 const double TEXT_OFF_X = -8.5, TEXT_OFF_Y = 3;
1291 ASSERT(xfrmr != NULL);
1292 ASSERT(xfrmr->info != NULL);
1295 draw_comp_bg(cr, pos_scale, VECT2(pos.x - 2, pos.y + 5.5),
1297 draw_xfrmr(cr, pos_scale, xfrmr->info);
1299 y = pos.y + TEXT_OFF_Y;
1301 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1302 "Type: Transformer");
1305 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1306 "Efficiency: %.1f%%", xfrmr->xfrmr.eff * 100);
1309 draw_comp_info(xfrmr, cr, pos_scale, font_sz,
1310 VECT2(pos.x + TEXT_OFF_X, y));
1314 draw_tie_info(
const elec_comp_t *tie, cairo_t *cr,
double pos_scale,
1315 double font_sz, vect2_t pos)
1317 const double TEXT_OFF_X = -6.5, TEXT_OFF_Y = 3;
1320 ASSERT(tie != NULL);
1321 ASSERT(tie->info != NULL);
1322 ASSERT3U(tie->info->type, ==,
ELEC_TIE);
1324 draw_comp_bg(cr, pos_scale, VECT2(pos.x, pos.y + 3.5), VECT2(14, 11));
1325 draw_tie(cr, pos_scale, tie);
1327 y = pos.y + TEXT_OFF_Y;
1329 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1330 "Type: Tie/Contactor");
1333 draw_comp_info(tie, cr, pos_scale, font_sz,
1334 VECT2(pos.x + TEXT_OFF_X, y));
1338 draw_batt_info(
const elec_comp_t *batt, cairo_t *cr,
double pos_scale,
1339 double font_sz, vect2_t pos)
1341 const double TEXT_OFF_X = -7.5, TEXT_OFF_Y = 3;
1344 ASSERT(batt != NULL);
1345 ASSERT(batt->info != NULL);
1346 ASSERT3U(batt->info->type, ==,
ELEC_BATT);
1348 draw_comp_bg(cr, pos_scale, VECT2(pos.x - 1.5, pos.y + 5.5),
1350 draw_batt(cr, pos_scale, batt->info,
false);
1352 y = pos.y + TEXT_OFF_Y;
1354 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1358 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1359 "Charge: %.1f%%", batt->batt.chg_rel * 100);
1362 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1363 "Temp: %.1f C", KELVIN2C(batt->batt.T));
1366 draw_comp_info(batt, cr, pos_scale, font_sz,
1367 VECT2(pos.x + TEXT_OFF_X, y));
1371 draw_load_info(
const elec_comp_t *load, cairo_t *cr,
double pos_scale,
1372 double font_sz, vect2_t pos)
1374 const double TEXT_OFF_X = -6.5, TEXT_OFF_Y = 3;
1378 ASSERT(load != NULL);
1379 ASSERT(load->info != NULL);
1380 ASSERT3U(load->info->type, ==,
ELEC_LOAD);
1382 draw_comp_bg(cr, pos_scale, VECT2(pos.x, pos.y + 3), VECT2(14, 10));
1383 draw_load(cr, pos_scale, font_sz, load->info);
1385 y = pos.y + TEXT_OFF_Y;
1387 switch (load->info->gui.load_type) {
1388 case GUI_LOAD_MOTOR:
1396 show_text_aligned(cr, PX(pos.x + TEXT_OFF_X), PX(y), TEXT_ALIGN_LEFT,
1400 draw_comp_info(load, cr, pos_scale, font_sz,
1401 VECT2(pos.x + TEXT_OFF_X, y));
1405 draw_bus_info(
const elec_comp_t *bus, cairo_t *cr,
double pos_scale,
1406 double font_sz, vect2_t pos)
1408 enum { LINE_H = 3 };
1409 unsigned comp_i = 0, num_loads = 0;
1410 double y, height, U;
1412 char name[MAX_NAME_LEN];
1414 ASSERT(bus != NULL);
1415 ASSERT(bus->info != NULL);
1416 ASSERT3U(bus->info->type, ==,
ELEC_BUS);
1418 for (
unsigned i = 0; i < bus->n_links; i++) {
1419 ASSERT(bus->links[i].comp != NULL);
1420 ASSERT(bus->links[i].comp->info != NULL);
1421 if (bus->links[i].comp->info->type ==
ELEC_CB)
1424 height = LINE_H * (1 + ceil(num_loads / 2.0));
1425 draw_comp_bg(cr, pos_scale, pos, VECT2(30, height));
1427 make_comp_name(bus->info->name, name);
1428 show_text_aligned(cr, PX(pos.x), PX(pos.y - height / 2 + 0.3 * LINE_H),
1429 TEXT_ALIGN_CENTER,
"%s", name);
1431 show_text_aligned(cr, PX(pos.x), PX(pos.y - height / 2 + 0.7 * LINE_H),
1432 TEXT_ALIGN_CENTER,
"U: %.*fV", fixed_decimals(U, 4), U);
1433 y = pos.y - height / 2 + LINE_H * 1.5;
1435 for (
unsigned i = 0; i < bus->n_links; i++) {
1436 const elec_comp_t *comp = bus->links[i].comp;
1444 cairo_set_line_width(cr, 3);
1445 if (comp_i % 2 == 0) {
1446 comp_pos = VECT2(pos.x - 7.5, y);
1447 cairo_move_to(cr, PX(comp_pos.x + 1), PX(y));
1449 comp_pos = VECT2(pos.x + 7.5, y);
1450 cairo_move_to(cr, PX(comp_pos.x - 1), PX(y));
1452 cairo_line_to(cr, PX(pos.x), PX(y));
1453 path = cairo_copy_path(cr);
1455 cairo_set_line_width(cr, 2);
1456 draw_src_path(cr, path, comp);
1458 if (comp_i + 2 < num_loads) {
1459 cairo_set_line_width(cr, 1);
1460 cairo_set_source_rgb(cr, 0.6, 0.6, 0.6);
1461 if (comp_i % 2 == 0) {
1462 cairo_move_to(cr, PX(pos.x - 14.5),
1463 PX(y + LINE_H / 2.0));
1464 cairo_rel_line_to(cr, PX(13.5), 0);
1466 cairo_move_to(cr, PX(pos.x + 14.5),
1467 PX(y + LINE_H / 2.0));
1468 cairo_rel_line_to(cr, PX(-13.5), 0);
1471 cairo_set_line_width(cr, 2);
1472 cairo_set_source_rgb(cr, 0, 0, 0);
1474 draw_cb_icon(cr, pos_scale, font_sz, comp_pos,
1475 info->cb.fuse, comp->scb.cur_set,
1476 info->cb.triphase, info->name,
1477 (vect3_t){COMP_INFO_BG_RGB}, comp);
1480 if (comp_i % 2 == 0) {
1481 show_text_aligned(cr, PX(pos.x - 14.5),
1482 PX(y - 0.33 * LINE_H), TEXT_ALIGN_LEFT,
1483 "I: %.*fA", fixed_decimals(I, 3), I);
1484 show_text_aligned(cr, PX(pos.x - 14.5), PX(y),
1486 "W: %.*fW", fixed_decimals(W, 3), W);
1487 show_text_aligned(cr, PX(pos.x - 1),
1488 PX(y - 0.33 * LINE_H), TEXT_ALIGN_RIGHT,
1489 "%s", comp->info->location);
1491 show_text_aligned(cr, PX(pos.x + 10.5),
1492 PX(y - 0.33 * LINE_H), TEXT_ALIGN_LEFT,
1493 "I: %.*fA", fixed_decimals(I, 3), I);
1494 show_text_aligned(cr, PX(pos.x + 10.5), PX(y),
1496 "W: %.*fW", fixed_decimals(W, 3), W);
1497 show_text_aligned(cr, PX(pos.x + 1),
1498 PX(y - 0.33 * LINE_H), TEXT_ALIGN_LEFT,
"%s", comp->info->location);
1501 if (comp_i % 2 == 0)
1505 cairo_set_line_width(cr, 10);
1506 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
1507 cairo_move_to(cr, PX(pos.x), PX(pos.y - height / 2 + LINE_H + 0.5));
1508 cairo_line_to(cr, PX(pos.x), PX(pos.y + height / 2 - LINE_H / 2));
1509 path = cairo_copy_path(cr);
1511 cairo_set_line_width(cr, 4);
1512 draw_src_path(cr, path, bus);
1513 cairo_set_line_cap(cr, CAIRO_LINE_CAP_BUTT);
1514 cairo_set_line_width(cr, 2);
1524 double pos_scale,
double font_sz, vect2_t pos)
1526 ASSERT(comp != NULL);
1529 cairo_set_source_rgb(cr, 0, 0, 0);
1530 cairo_set_font_size(cr, font_sz);
1531 cairo_set_line_width(cr, 2);
1533 ASSERT(comp->info != NULL);
1534 switch (comp->info->type) {
1536 draw_batt_info(comp, cr, pos_scale, font_sz, pos);
1539 draw_gen_info(comp, cr, pos_scale, font_sz, pos);
1543 draw_tru_inv_info(comp, cr, pos_scale, font_sz, pos);
1546 draw_xfrmr_info(comp, cr, pos_scale, font_sz, pos);
1549 draw_load_info(comp, cr, pos_scale, font_sz, pos);
1552 draw_bus_info(comp, cr, pos_scale, font_sz, pos);
1556 draw_scb_info(comp, cr, pos_scale, font_sz, pos);
1559 draw_tie_info(comp, cr, pos_scale, font_sz, pos);
1562 draw_diode_info(comp, cr, pos_scale, font_sz, pos);
bool libelec_comp_is_AC(const elec_comp_t *comp)
double libelec_comp_get_out_amps(const elec_comp_t *comp)
double libelec_comp_get_out_freq(const elec_comp_t *comp)
bool libelec_cb_get(const elec_comp_t *comp)
double libelec_comp_get_out_pwr(const elec_comp_t *comp)
const elec_comp_info_t * libelec_comp2info(const elec_comp_t *comp)
double libelec_comp_get_in_freq(const elec_comp_t *comp)
double libelec_comp_get_in_volts(const elec_comp_t *comp)
double libelec_comp_get_in_pwr(const elec_comp_t *comp)
double libelec_comp_get_in_amps(const elec_comp_t *comp)
double libelec_comp_get_out_volts(const elec_comp_t *comp)
void libelec_draw_comp_info(const elec_comp_t *comp, cairo_t *cr, double pos_scale, double font_sz, vect2_t pos)
void libelec_draw_layout(const elec_sys_t *sys, cairo_t *cr, double pos_scale, double font_sz)