NEURON
shape.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include "classreg.h"
3 #include "gui-redirect.h"
4 
5 #if HAVE_IV // to end of file
6 
7 #define BEVELJOIN 1
8 #include <InterViews/display.h>
9 #include <InterViews/session.h>
10 #include <InterViews/background.h>
11 #include <InterViews/style.h>
12 #include <InterViews/window.h>
13 #include <InterViews/tformsetter.h>
14 #include <InterViews/brush.h>
15 #include <InterViews/action.h>
16 #include <InterViews/color.h>
17 #include <InterViews/hit.h>
18 #include <InterViews/handler.h>
19 #include <InterViews/event.h>
20 #include <InterViews/telltale.h>
21 #include <InterViews/layout.h>
22 #include <IV-look/kit.h>
23 #include <OS/list.h>
24 #include <ivstream.h>
25 #include <math.h>
26 #include "mymath.h"
27 #include "apwindow.h"
28 // really only need colors from graph.h
29 #include "graph.h"
30 #include "shapeplt.h"
31 #include "rubband.h"
32 #include "scenepic.h"
33 #include "rot3band.h"
34 #include "nrnoc2iv.h"
35 #include "objcmd.h"
36 #include "idraw.h"
37 #include "hocmark.h"
38 #include "ocobserv.h"
39 #include "parse.hpp"
40 #include "ivoc.h"
41 
42 #define Shape_Section_ "Section PlotShape"
43 #define Shape_Rotate_ "Rotate3D PlotShape"
44 #define Shape_Style_ "ShapeStyle PlotShape"
45 
46 void nrn_define_shape();
47 extern int nrn_shape_changed_;
48 extern "C" int structure_change_cnt;
49 extern int section_count;
50 extern Section** secorder;
51 extern "C" Point_process* ob2pntproc(Object*);
52 extern "C" Point_process* ob2pntproc_0(Object*);
53 extern "C" double* nrn_recalc_ptr(double*);
54 extern Object* (*nrnpy_seg_from_sec_x)(Section*, double);
55 
56 #if BEVELJOIN
57 static long beveljoin_ = 0;
58 #endif
59 
60 static ShapeScene* volatile_ptr_ref;
61 
62 class ShapeChangeObserver: public Observer {
63  public:
64  ShapeChangeObserver(ShapeScene*);
65  virtual ~ShapeChangeObserver();
66  virtual void update(Observable*);
67  void force();
68  bool needs_update() {
69  return (shape_changed_ != nrn_shape_changed_);
70  }
71 
72  private:
73  int shape_changed_;
74  int struc_changed_;
75  ShapeScene* s_;
76 };
77 
78 static const Color* sec_sel_color() {
79  static const Color* lt = NULL;
80  if (!lt) {
81  String c;
82  Display* dis = Session::instance()->default_display();
83  if (!dis->style()->find_attribute("section_select_color", c) ||
84  (lt = Color::lookup(dis, c)) == NULL) {
85  lt = Color::lookup(dis, "#ff0000");
86  }
87  lt->ref();
88  }
89  return lt;
90 }
91 
92 static const Color* sec_adjacent_color() {
93  static const Color* lt = NULL;
94  if (!lt) {
95  String c;
96  Display* dis = Session::instance()->default_display();
97  if (!dis->style()->find_attribute("section_adjacent_color", c) ||
98  (lt = Color::lookup(dis, c)) == NULL) {
99  lt = Color::lookup(dis, "#00ff00");
100  }
101  lt->ref();
102  }
103  return lt;
104 }
105 
106 inline float norm(float x, float y) {
107  return (x * x + y * y);
108 }
109 
110 /* static */ class OcShape;
111 // must be append_fixed to OcShape or else...
112 /* static */ class PointMark: public MonoGlyph, public Observer {
113  public:
114  PointMark(OcShape*, Object*, const Color*, const char style = 'O', float size = 8.);
115  virtual ~PointMark();
116  virtual void update(Observable*);
117  virtual void disconnect(Observable*);
118  virtual void draw(Canvas*, const Allocation&) const;
119  const Object* object() {
120  return ob_;
121  }
122  virtual void set_loc(Section*, float x);
123  bool everything_ok();
124 
125  private:
126  GlyphIndex i_;
127  Coord x_, y_;
128  Object* ob_;
129  OcShape* sh_;
130  Section* sec_;
131  float xloc_;
132 };
133 
134 class OcShapeHandler;
135 /* static */ class OcShape: public ShapeScene {
136  public:
137  OcShape(SectionList* = NULL);
138  virtual ~OcShape();
139  virtual void select_section(Section*);
140  virtual void handle_picked();
141  virtual void selected(ShapeSection* s, Coord x, Coord y) {
142  ShapeScene::selected(s, x, y);
143  }
144  virtual ShapeSection* selected() {
145  return ShapeScene::selected();
146  }
147  virtual void set_select_action(const char*);
148  virtual void set_select_action(Object*);
149  virtual void save_phase1(ostream&);
150  virtual PointMark* point_mark(Object*,
151  const Color*,
152  const char style = 'O',
153  const float size = 8.);
154  virtual PointMark* point_mark(Section*, float x, const Color*);
155  virtual void point_mark_remove(Object* pp = NULL);
156  virtual void transform3d(Rubberband* rb = NULL);
157  virtual void erase_all();
158  virtual void sel_color(ShapeSection* sold, ShapeSection* snew);
159 
160  private:
161  HocCommand* select_;
162  PolyGlyph* point_mark_list_;
163  OcShapeHandler* osh_;
164  ShapeSection* sold_;
165  bool show_adjacent_selection_;
166 };
167 
168 /*static*/ class OcShapeHandler: public SectionHandler {
169  public:
170  OcShapeHandler(OcShape*);
171  virtual ~OcShapeHandler();
172  virtual bool event(Event&);
173 
174  private:
175  OcShape* s_;
176 };
177 OcShapeHandler::OcShapeHandler(OcShape* s) {
178  s_ = s;
179 }
180 OcShapeHandler::~OcShapeHandler() {}
181 bool OcShapeHandler::event(Event&) {
182  s_->handle_picked();
183  return true;
184 }
185 #endif // HAVE_IV
186 
187 extern Object** (*nrnpy_gui_helper_)(const char* name, Object* obj);
188 extern double (*nrnpy_object_to_double_)(Object*);
189 
190 // Shape class registration for oc
191 static double sh_view(void* v) {
192  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.view", v);
193 #if HAVE_IV
194  IFGUI
195  OcShape* sh = (OcShape*) v;
196  if (ifarg(8)) {
197  Coord x[8];
198  int i;
199  for (i = 0; i < 8; ++i) {
200  x[i] = *getarg(i + 1);
201  }
202  sh->view(x);
203  }
204  ENDGUI
205 #endif
206  return 1.;
207 }
208 
209 static double sh_flush(void* v) {
210  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.flush", v);
211 #if HAVE_IV
212  IFGUI((ShapeScene*) v)->flush();
213  ENDGUI
214 #endif
215  return 1.;
216 }
217 
218 static double sh_begin(void* v) { // a noop. Exists only because graphs and
219  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.begin", v);
220  return 1.; // shapes are often in same list
221 }
222 
223 static double sh_save_name(void* v) {
224  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.save_name", v);
225 #if HAVE_IV
226  IFGUI((ShapeScene*) v)->name(gargstr(1));
227  ENDGUI
228 #endif
229  return 1.;
230 }
231 
232 static double sh_select(void* v) {
233  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.select", v);
234 #if HAVE_IV
235  IFGUI
236  Section* sec = chk_access();
237  ((OcShape*) v)->select_section(sec);
238  ENDGUI
239 #endif
240  return 1.;
241 }
242 static double sh_select_action(void* v) {
243  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.action", v);
244 #if HAVE_IV
245  IFGUI
246  if (hoc_is_object_arg(1)) {
247  ((OcShape*) v)->set_select_action(*hoc_objgetarg(1));
248  } else {
249  ((OcShape*) v)->set_select_action(gargstr(1));
250  }
251  ENDGUI
252 #endif
253  return 1.;
254 }
255 
256 static double sh_view_count(void* v) {
257  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.view_count", v);
258  int n = 0;
259 #if HAVE_IV
260  IFGUI
261  n = ((ShapeScene*) v)->view_count();
262  ENDGUI
263 #endif
264  return double(n);
265 }
266 
267 double nrniv_sh_nearest(void* v) {
268  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.nearest", v);
269  double d = 0.;
270 #if HAVE_IV
271  IFGUI
272  d = ((ShapeScene*) v)->nearest(*getarg(1), *getarg(2));
273  ENDGUI
274 #endif
275  return d;
276 }
277 
278 double nrniv_sh_push(void* v) {
279  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.push_seleced", v);
280  double d = -1.;
281 #if HAVE_IV
282  IFGUI
283  ShapeScene* ss = (ShapeScene*) v;
284  ShapeSection* s = ss->selected();
285  if (s && s->good()) {
286  nrn_pushsec(s->section());
287  d = ss->arc_selected();
288  }
289  ENDGUI
290 #endif
291  return d;
292 }
293 
295  TRY_GUI_REDIRECT_ACTUAL_OBJ("Shape.nearest_seg", v);
296  Object* obj = NULL;
297 #if HAVE_IV
298  IFGUI
299  ShapeScene* ss = (ShapeScene*) v;
300  ShapeSection* ssec = NULL;
301  double d = ss->nearest(*getarg(1), *getarg(2));
302  ssec = ss->selected();
303  if (d < 1e15 && nrnpy_seg_from_sec_x && ssec) {
304  d = ss->arc_selected();
305  obj = (*nrnpy_seg_from_sec_x)(ssec->section(), d);
306  }
307  --obj->refcount;
308  ENDGUI
309 #endif
310  return hoc_temp_objptr(obj);
311 }
312 
314  TRY_GUI_REDIRECT_ACTUAL_OBJ("Shape.selected_seg", v);
315  Object* obj = NULL;
316 #if HAVE_IV
317  IFGUI
318  ShapeScene* ss = (ShapeScene*) v;
319  ShapeSection* ssec = NULL;
320  ssec = ss->selected();
321  if (nrnpy_seg_from_sec_x && ssec) {
322  double d = ss->arc_selected();
323  obj = (*nrnpy_seg_from_sec_x)(ssec->section(), d);
324  }
325  --obj->refcount;
326  ENDGUI
327 #endif
328  return hoc_temp_objptr(obj);
329 }
330 
331 double nrniv_sh_observe(void* v) {
332  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.observe", v);
333 #if HAVE_IV
334  IFGUI
335  ShapeScene* s = (ShapeScene*) v;
336  SectionList* sl = NULL;
337  if (ifarg(1)) {
338  Object* o = *hoc_objgetarg(1);
339  check_obj_type(o, "SectionList");
340  sl = new SectionList(o);
341  sl->ref();
342  s->observe(sl);
343  sl->unref();
344  } else {
345  s->observe(NULL);
346  }
347  ENDGUI
348 #endif
349  return 0.;
350 }
351 
352 double nrniv_sh_rotate(void* v) {
353  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.rotate", v);
354 #if HAVE_IV
355  IFGUI
356  ShapeScene* s = (ShapeScene*) v;
357  if (!ifarg(1)) {
358  // identity
359  s->rotate();
360  } else {
361  // defines origin (absolute) and rotation
362  // (relative to the current coord system)
363  s->rotate(*getarg(1), *getarg(2), *getarg(3), *getarg(4), *getarg(5), *getarg(6));
364  }
365  ENDGUI
366 #endif
367  return 0.;
368 }
369 
370 static double sh_unmap(void* v) {
371  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.unmap", v);
372 #if HAVE_IV
373  IFGUI
374  ShapeScene* s = (ShapeScene*) v;
375  s->dismiss();
376  ENDGUI
377 #endif
378  return 0.;
379 }
380 
381 double nrniv_sh_color(void* v) {
382  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.color", v);
383 #if HAVE_IV
384  IFGUI
385  ShapeScene* s = (ShapeScene*) v;
386  const Color* c = NULL;
387  c = colors->color(int(*getarg(1)));
388  if (ifarg(2)) {
389  Section* sec;
390  double x;
391  nrn_seg_or_x_arg(2, &sec, &x);
392  s->colorseg(sec, x, c);
393  } else {
394  s->color(chk_access(), c);
395  }
396  ENDGUI
397 #endif
398  return 0.;
399 }
400 
401 double nrniv_sh_color_all(void* v) {
402  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.color_all", v);
403 #if HAVE_IV
404  IFGUI
405  ShapeScene* s = (ShapeScene*) v;
406  const Color* c = NULL;
407  c = colors->color(int(*getarg(1)));
408  s->color(c);
409  ENDGUI
410 #endif
411  return 0.;
412 }
413 
414 double nrniv_sh_color_list(void* v) {
415  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.color_list", v);
416 #if HAVE_IV
417  IFGUI
418  ShapeScene* s = (ShapeScene*) v;
419  const Color* c = NULL;
420  c = colors->color(int(*getarg(2)));
421  s->color(new SectionList(*hoc_objgetarg(1)), c);
422  ENDGUI
423 #endif
424  return 0.;
425 }
426 
427 static double sh_point_mark(void* v) {
428  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.point_mark", v);
429 #if HAVE_IV
430  IFGUI
431  OcShape* s = (OcShape*) v;
432  char style = 'O';
433  float size = 8.;
434  if (hoc_is_object_arg(1)) {
435  if (ifarg(3)) {
436  if (hoc_is_str_arg(3)) {
437  style = *gargstr(3);
438  } else {
439  style = char(chkarg(3, 0, 127));
440  }
441  }
442  if (ifarg(4)) {
443  size = float(chkarg(4, 1e-9, 1e9));
444  }
445  s->point_mark(*hoc_objgetarg(1), colors->color(int(*getarg(2))), style, size);
446  } else {
447  s->point_mark(chk_access(), chkarg(1, 0., 1.), colors->color(int(*getarg(2))));
448  }
449  ENDGUI
450 #endif
451  return 0.;
452 }
453 
454 static double sh_point_mark_remove(void* v) {
455  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.point_mark_remove", v);
456 #if HAVE_IV
457  IFGUI
458  Object* o = NULL;
459  OcShape* s = (OcShape*) v;
460  if (ifarg(1)) {
461  o = *hoc_objgetarg(1);
462  }
463  s->point_mark_remove(o);
464  ENDGUI
465 #endif
466  return 0.;
467 }
468 
469 static double sh_printfile(void* v) {
470  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.printfile", v);
471 #if HAVE_IV
472  IFGUI
473  ShapeScene* s = (ShapeScene*) v;
474  s->printfile(gargstr(1));
475  ENDGUI
476 #endif
477  return 1.;
478 }
479 
480 static double sh_show(void* v) {
481  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.show", v);
482 #if HAVE_IV
483  IFGUI
484  ShapeScene* s = (ShapeScene*) v;
485  s->shape_type(int(chkarg(1, 0., 2.)));
486  ENDGUI
487 #endif
488  return 1.;
489 }
490 
491 
492 extern double ivoc_gr_menu_action(void* v);
493 
494 static double exec_menu(void* v) {
495  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.exec_menu", v);
496 #if HAVE_IV
497  IFGUI((Scene*) v)->picker()->exec_item(gargstr(1));
498  ENDGUI
499 #endif
500  return 0.;
501 }
502 
503 double nrniv_len_scale(void* v) {
504  TRY_GUI_REDIRECT_ACTUAL_DOUBLE("Shape.len_scale", v);
505 #if HAVE_IV
506  IFGUI
507  ShapeScene* scene = (ShapeScene*) v;
508  ShapeSection* ss = scene->shape_section(chk_access());
509  if (ss) {
510  if (ifarg(1)) {
511  ss->scale(chkarg(1, 1e-9, 1e9));
512  scene->force();
513  }
514  return ss->scale();
515  }
516  ENDGUI
517 #endif
518  return 0.;
519 }
520 
521 extern double ivoc_gr_menu_tool(void*);
522 extern double ivoc_gr_mark(void*);
523 extern double ivoc_gr_size(void*);
524 extern double ivoc_gr_label(void*);
525 extern double ivoc_gr_line(void*);
526 extern double ivoc_gr_begin_line(void*);
527 extern double ivoc_gr_erase(void*);
528 extern double ivoc_gr_gif(void*);
529 extern double ivoc_erase_all(void*);
530 
531 static Member_func sh_members[] = {"nearest",
533  "push_selected",
535  "view",
536  sh_view,
537  "size",
538  ivoc_gr_size,
539  "flush",
540  sh_flush,
541  "begin",
542  sh_begin,
543  "view_count",
545  "select",
546  sh_select,
547  "action",
549  "save_name",
550  sh_save_name,
551  "unmap",
552  sh_unmap,
553  "color",
555  "color_all",
557  "color_list",
559  "point_mark",
561  "point_mark_remove",
563  "point_mark_remove",
565  "printfile",
566  sh_printfile,
567  "show",
568  sh_show,
569  "menu_action",
571  "menu_tool",
573  "exec_menu",
574  exec_menu,
575  "observe",
577  "rotate",
579  "beginline",
581  "line",
582  ivoc_gr_line,
583  "label",
585  "mark",
586  ivoc_gr_mark,
587  "erase",
589  "erase_all",
591  "len_scale",
593  "gif",
594  ivoc_gr_gif,
595  0,
596  0};
597 
599  {"nearest_seg", nrniv_sh_nearest_seg, "selected_seg", nrniv_sh_selected_seg, NULL, NULL};
600 
601 
602 static void* sh_cons(Object* ho) {
603  TRY_GUI_REDIRECT_OBJ("Shape", NULL);
604 #if HAVE_IV
605  OcShape* sh = NULL;
606  IFGUI
607  int i = 1;
608  int iarg = 1;
609  SectionList* sl = NULL;
610  // first arg may be an object.
611  if (ifarg(iarg)) {
612  if (hoc_is_object_arg(iarg)) {
613  sl = new SectionList(*hoc_objgetarg(iarg));
614  sl->ref();
615  ++iarg;
616  }
617  }
618  if (ifarg(iarg)) {
619  i = int(chkarg(iarg, 0, 1));
620  }
621  sh = new OcShape(sl);
623  sh->ref();
624  sh->hoc_obj_ptr(ho);
625  if (i) {
626  sh->view(200);
627  }
628  ENDGUI
629  return (void*) sh;
630 #endif
631  return 0;
632 }
633 static void sh_destruct(void* v) {
634  TRY_GUI_REDIRECT_NO_RETURN("~Shape", v);
635 #if HAVE_IV
636  IFGUI((ShapeScene*) v)->dismiss();
637  Resource::unref((OcShape*) v);
638  ENDGUI
639 #endif
640 }
641 void Shape_reg() {
642  // printf("Shape_reg\n");
644 }
645 
646 #if HAVE_IV
647 
648 OcShape::OcShape(SectionList* sl)
649  : ShapeScene(sl) {
650  select_ = NULL;
651  point_mark_list_ = NULL;
652  osh_ = new OcShapeHandler(this);
653  osh_->ref();
654  section_handler(osh_);
655  sold_ = NULL;
656  Display* dis = Session::instance()->default_display();
657  show_adjacent_selection_ = dis->style()->value_is_on("show_adjacent_selection");
658 }
659 OcShape::~OcShape() {
660  if (select_)
661  delete select_;
662  Resource::unref(point_mark_list_);
663  osh_->unref();
664  Resource::unref(sold_);
665 }
666 
667 void OcShape::erase_all() {
668  Resource::unref(point_mark_list_);
669  point_mark_list_ = NULL;
671 }
672 
673 PointMark* OcShape::point_mark(Object* ob, const Color* c, const char style, const float size) {
674  if (!point_mark_list_) {
675  point_mark_list_ = new PolyGlyph();
676  }
677  PointMark* g = new PointMark(this, ob, c, style, size);
678  point_mark_list_->append(g);
679  append_fixed(new GraphItem(g, 0));
680  if (!g->everything_ok()) {
681  point_mark_list_->remove(point_mark_list_->count() - 1);
682  remove(glyph_index(g));
683  return NULL;
684  }
685  return g;
686 }
687 
688 PointMark* OcShape::point_mark(Section* sec, float x, const Color* c) {
689  if (!point_mark_list_) {
690  point_mark_list_ = new PolyGlyph();
691  }
692  PointMark* g = new PointMark(this, NULL, c);
693  g->set_loc(sec, x);
694  point_mark_list_->append(g);
695  append_fixed(new GraphItem(g, 0));
696  if (!g->everything_ok()) {
697  point_mark_list_->remove(point_mark_list_->count() - 1);
698  remove(glyph_index(g));
699  return NULL;
700  }
701  return g;
702 }
703 void OcShape::point_mark_remove(Object* o) {
704  if (point_mark_list_) {
705  if (o) {
706  GlyphIndex i, cnt = point_mark_list_->count();
707  for (i = cnt - 1; i >= 0; --i) {
708  PointMark* g = (PointMark*) point_mark_list_->component(i);
709  if (g->object() == o) {
710  remove(glyph_index(g));
711  point_mark_list_->remove(i);
712  break;
713  }
714  }
715  } else {
716  while (point_mark_list_->count()) {
717  remove(glyph_index(point_mark_list_->component(0)));
718  point_mark_list_->remove(0);
719  }
720  }
721  }
722 }
723 
724 void OcShape::set_select_action(const char* s) {
725  if (select_) {
726  delete select_;
727  }
728  select_ = new HocCommand(s);
729 }
730 
731 void OcShape::set_select_action(Object* pobj) {
732  if (select_) {
733  delete select_;
734  }
735  select_ = new HocCommand(pobj);
736 }
737 
738 void OcShape::sel_color(ShapeSection* sold, ShapeSection* snew) {
739  ShapeSection* ss;
740  Section* s;
741  const Color* c;
742  if (sold) {
744  s = sold->section();
745  sold->setColor(c, this);
746  if (show_adjacent_selection_) {
747  ss = shape_section(s->parentsec);
748  if (ss) {
749  ss->setColor(c, this);
750  }
751  for (s = s->child; s; s = s->sibling) {
752  ss = shape_section(s);
753  if (ss) {
754  ss->setColor(c, this);
755  }
756  }
757  }
758  }
759  if (snew) {
760  c = sec_sel_color();
761  snew->setColor(c, this);
762  c = sec_adjacent_color();
763  s = snew->section();
764  if (show_adjacent_selection_) {
765  ss = shape_section(s->parentsec);
766  if (ss) {
767  ss->setColor(c, this);
768  }
769  for (s = s->child; s; s = s->sibling) {
770  ss = shape_section(s);
771  if (ss) {
772  ss->setColor(c, this);
773  }
774  }
775  }
776  }
777 }
778 void OcShape::select_section(Section* sec) {
780  ShapeSection* ss;
781  Section* s;
782  const Color* c;
783  ss = shape_section(sec);
784  sel_color(s1, ss);
785  if (ss) {
787  Resource::ref(ss);
788  Resource::unref(sold_);
789  sold_ = ss;
790  }
791 }
792 void OcShape::handle_picked() {
794  if (!s1 || !s1->good()) {
795  return;
796  }
797  sel_color(sold_, s1);
798  if (sold_) {
799  sold_->unref();
800  }
801  sold_ = s1;
802  sold_->ref();
803  if (select_) {
804  nrn_pushsec(s1->section());
805  hoc_ac_ = arc_selected();
806  // printf("arc_selected %g\n", hoc_ac_);
807  select_->execute();
808  nrn_popsec();
809  }
810 }
811 
812 void OcShape::save_phase1(ostream& o) {
813  o << "{" << endl;
814  save_class(o, "Shape");
815 }
816 
817 #if 1
818 // ShapeView
819 
821  : View((s->x1() + s->x2()) / 2,
822  (s->y1() + s->y2()) / 2,
823  Math::max(s->x2() - s->x1(), s->y2() - s->y1()) * 1.1,
824  s
825  // ,150*(s->x2() - s->x1())/Math::max(s->x2() - s->x1(), s->y2() - s->y1()),
826  // 150*(s->y2() - s->y1())/Math::max(s->x2() - s->x1(), s->y2() - s->y1())
827  ) {}
828 
830  : View(x[0], x[1], x[2], x[3], s, x[6], x[7]) {
831  Coord x1, y1, x2, y2;
832  zout(x1, y1, x2, y2);
833  size(x1, y1, x2, y2);
834 }
835 
837 
838 #endif
839 
840 /* static */ class ShapeType: public Action {
841  public:
842  ShapeType(int);
843  virtual ~ShapeType();
844  virtual void execute();
845 
846  private:
847  int shapetype_;
848 };
849 ShapeType::ShapeType(int st) {
850  shapetype_ = st;
851 }
852 ShapeType::~ShapeType() {}
853 void ShapeType::execute() {
854  if (Oc::helpmode()) {
855  Oc::help(Shape_Style_);
856  }
858 }
859 
860 
861 // declareHandlerCallback(ShapeScene)
862 // implementHandlerCallback(ShapeScene)
864  declareActionCallback(ShapeScene) implementActionCallback(ShapeScene)
865 
867  GlyphIndex i, cnt;
868  hoc_Item* qsec;
869  Section* sec;
870  ShapeSection* gl;
871  while (sg_->count()) {
872  gl = (ShapeSection*) sg_->component(sg_->count() - 1);
873  i = glyph_index(gl);
874  remove(i);
875  sg_->remove(sg_->count() - 1);
876  }
877  if (sl) { // haven't figured out a way to save this
878  view_all_ = false;
879  for (sec = sl->begin(); sec; sec = sl->next()) {
880  gl = new ShapeSection(sec);
881  append(new FastGraphItem(gl, 0));
882  sg_->append(gl);
883  }
884  } else {
885  view_all_ = true;
886  // ForAllSections(sec)
887  ITERATE(qsec, section_list) {
888  Section* sec = hocSEC(qsec);
889  gl = new ShapeSection(sec);
890  append(new FastGraphItem(gl, 0));
891  sg_->append(gl);
892  }
893  }
894  recalc_diam();
895  selected_ = NULL;
896  volatile_ptr_ref = NULL;
897  transform3d();
898  if (shape_changed_) {
899  force();
900  flush();
901  }
902 }
903 
904 void ShapeScene::force() {
905  shape_changed_->force();
906 }
907 
909  : Graph(0) {
911  new_size(-100, -100, 100, 100);
912  erase_axis();
913  WidgetKit& wk = *WidgetKit::instance();
914  sg_ = new PolyGlyph();
915  sg_->ref();
916  shape_changed_ = NULL; // observe not ready for it yet
918  r3b_->ref();
919  observe(sl);
920  var_name_ = NULL;
921  wk.style()->find_attribute("shape_beveljoin", beveljoin_);
922 
923  MenuItem* mi;
924  Menu* m;
925 
926  shape_type_ = ShapeScene::show_centroid;
927  section_handler_ = NULL;
928 
929  selected_ = NULL;
930  picker();
931  picker()->remove_item("Crosshair");
932  picker()->remove_item("Plot what?");
933  picker()->remove_item("Pick Vector");
934  picker()->remove_item("Color/Brush");
935  picker()->remove_item("Keep Lines");
936  picker()->remove_item("Family Label?");
937  picker()->remove_item("Erase");
938  picker()->remove_item("Remove");
939 
940  picker()->bind_select((OcHandler*) NULL);
941  MenuItem* m2 = picker()->add_radio_menu("Section", (OcHandler*) NULL, SECTION);
942  m2->state()->set(TelltaleState::is_chosen, true);
943  picker()->add_radio_menu("3D Rotate", r3b_, 0, ROTATE);
944  picker()->add_menu("Redraw Shape", new ActionCallback(ShapeScene)(this, &ShapeScene::flush));
945 
946  m = wk.pullright();
947  mi = wk.menu_item("Show Diam");
948  mi->action(new ShapeType(ShapeScene::show_diam));
949  picker()->add_menu("Show Diam", mi, m);
950  mi = wk.menu_item("Centroid");
951  mi->action(new ShapeType(ShapeScene::show_centroid));
952  picker()->add_menu("Centroid", mi, m);
953  mi = wk.menu_item("Schematic");
954  mi->action(new ShapeType(ShapeScene::show_schematic));
955  picker()->add_menu("Schematic", mi, m);
956  mi = wk.menu_item("Shape Style");
957  mi->menu(m);
958  picker()->add_menu(mi);
959 
960  Requisition req;
961  Coord x1, y1, x2, y2;
962  Coord xt1 = 0, yt1 = 0, xt2 = 0, yt2 = 0;
963  GlyphIndex i, cnt = count();
964  for (i = 0; i < cnt; ++i) {
965  component(i)->request(req);
966  MyMath::box(req, x1, y1, x2, y2);
967  xt1 = Math::min(x1, xt1);
968  yt1 = Math::min(y1, yt1);
969  xt2 = Math::max(x2, xt2);
970  yt2 = Math::max(y2, yt2);
971  }
972  Scene::new_size(xt1, yt1, xt2, yt2);
973  color_value_ = new ColorValue();
974  Resource::ref(color_value_);
975  shape_changed_ = new ShapeChangeObserver(this);
976 }
977 
978 void ShapeScene::help() {
979  switch (tool()) {
980  case SECTION:
981  Oc::help(Shape_Section_);
982  break;
983  case ROTATE:
984  Oc::help(Shape_Rotate_);
985  break;
986  default:
987  Scene::help();
988  break;
989  }
990 }
991 
992 #if 0
994 #endif
995 
997  volatile_ptr_ref = NULL;
1002  delete shape_changed_;
1003  if (var_name_) {
1004  delete var_name_;
1005  }
1006 }
1007 
1008 void ShapeScene::erase_all() {
1010  sg_ = new PolyGlyph();
1011  sg_->ref();
1012  volatile_ptr_ref = NULL;
1013  Graph::erase_all();
1014 }
1015 
1016 void ShapeScene::rotate() {
1017  Rotation3d* rot = r3b_->rotation();
1018  rot->identity();
1019  transform3d();
1020 }
1021 
1022 void ShapeScene::rotate(Coord xorg, Coord yorg, Coord zorg, float xrad, float yrad, float zrad) {
1023  Rotation3d* rot = r3b_->rotation();
1024  rot->origin(xorg, yorg, zorg);
1025  rot->rotate_x(xrad);
1026  rot->rotate_y(yrad);
1027  rot->rotate_z(zrad);
1028  transform3d();
1029 }
1030 
1032  Rotation3d* rot = r3b_->rotation();
1033  Coord x, y;
1034  // rb->transformer().inverse_transform(rb->x_begin(), rb->y_begin(), x, y);
1035  // printf("ShapeScene::transform3d %g %g\n", x, y);
1036  long i, n;
1037  for (i = 0; i < section_count; ++i) {
1039  if (ss) {
1040  ss->transform3d(rot);
1041  }
1042  }
1043  n = count();
1044  for (i = 0; i < n; ++i) {
1045  modified(i);
1046  }
1047 }
1048 
1049 void ShapeScene::flush() {
1050  if (shape_changed_->needs_update()) {
1051  shape_changed_->update(NULL);
1052  } else {
1053  damage_all();
1054  }
1055 }
1056 
1057 void ShapeScene::wholeplot(Coord& x1, Coord& y1, Coord& x2, Coord& y2) const {
1058  long i, j, n = sg_->count();
1059  Coord l, b, r, t;
1060  x1 = y1 = 1e9;
1061  x2 = y2 = -1e9;
1062  for (i = 0; i < n; ++i) {
1063  ((ShapeSection*) sg_->component(i))->size(l, b, r, t);
1064  x1 = Math::min(x1, l);
1065  x2 = Math::max(x2, r);
1066  y1 = Math::min(y1, b);
1067  y2 = Math::max(y2, t);
1068  }
1069  if (x1 >= x2 || y1 >= y2) {
1070  Scene::wholeplot(x1, y1, x2, y2);
1071  }
1072 }
1073 
1074 ColorValue* ShapeScene::color_value() {
1075  return color_value_;
1076 }
1078  return sg_;
1079 }
1080 
1081 void ShapeScene::name(const char* s) {
1082  if (!var_name_) {
1083  var_name_ = new CopyString(s);
1084  } else {
1085  *var_name_ = s;
1086  }
1087 }
1088 
1089 void ShapeScene::save_phase2(ostream& o) {
1090  char buf[256];
1091  if (var_name_) {
1092  if ((var_name_->string())[var_name_->length() - 1] == '.') {
1093  sprintf(buf, "%sappend(save_window_)", var_name_->string());
1094  } else {
1095  sprintf(buf, "%s = save_window_", var_name_->string());
1096  }
1097  o << buf << endl;
1098  sprintf(buf, "save_window_.save_name(\"%s\")", var_name_->string());
1099  o << buf << endl;
1100  }
1102 }
1103 
1104 void ShapeScene::view(Rubberband* rb) {
1105  Coord x1, y1, x2, y2, t, b, l, r;
1106  ((RubberRect*) rb)->get_rect_canvas(l, b, r, t);
1107  ((RubberRect*) rb)->get_rect(x1, y1, x2, y2);
1108  printf("new view with %g %g %g %g\n", x1, y1, x2, y2);
1109 #if 0
1110  double d1, d2; int ntic;
1111  MyMath::round_range(x1, x2, d1, d2, ntic);
1112  x1 = d1;
1113  x2 = d2;
1114  MyMath::round_range(y1, y2, d1, d2, ntic);
1115  y1 = d1;
1116  y2 = d2;
1117 #endif
1118  View* v;
1119  ViewWindow* w = new ViewWindow(v = new View((x2 + x1) / 2,
1120  (y1 + y2) / 2,
1121  x2 - x1,
1122  this,
1123  r - l,
1124  (r - l) * (y2 - y1) / (x2 - x1)),
1125  "Shape");
1126  const Event& e = rb->event();
1127  w->place(l + e.pointer_root_x() - e.pointer_x(), b + e.pointer_root_y() - e.pointer_y());
1128  w->map();
1129 }
1130 
1132  Resource::ref(h);
1134  section_handler_ = h;
1135 }
1136 
1138  if (section_handler_) {
1140  }
1141  return section_handler_;
1142 }
1144  return section_handler_;
1145 }
1146 
1147 void ShapeScene::shape_type(int s) {
1148  shape_type_ = s;
1149  damage_all();
1150 }
1151 
1152 float ShapeScene::nearest(Coord x, Coord y) {
1153  GlyphIndex i, cnt = sg_->count();
1154  float d2, d = 1e20;
1155  for (i = 0; i < cnt; ++i) {
1156  ShapeSection* ss = (ShapeSection*) sg_->component(i);
1157  if (ss->good()) {
1158  d2 = ss->how_near(x, y);
1159  if (d2 < d) {
1160  selected(ss, x, y);
1161  d = d2;
1162  }
1163  }
1164  }
1165  // printf("nearest %s %g\n", hoc_section_pathname(selected()->section()), d);
1166  return d;
1167 }
1168 
1170  GlyphIndex i, cnt = sg_->count();
1171  if (this != volatile_ptr_ref) {
1172  volatile_ptr_ref = this;
1173  for (i = 0; i < section_count; ++i) {
1175  }
1176  for (i = 0; i < cnt; ++i) {
1177  ShapeSection* ss = (ShapeSection*) sg_->component(i);
1178  if (ss->good()) {
1179  ss->section()->volatile_ptr = ss;
1180  }
1181  }
1182  }
1183  return sec ? (ShapeSection*) sec->volatile_ptr : NULL;
1184 }
1185 
1186 // color the shapesections
1187 
1188 static bool par_helper(Section* sec) {
1189  /* decide whether a sec with 2 marks should be colored. yes if
1190  there are not two single marked children connected at same location
1191  or any double marked children */
1192  Section* csec;
1193  double y, x = -1.;
1194  for (csec = sec->child; csec; csec = csec->sibling) {
1195  switch (nrn_value_mark(csec)) {
1196  case 1:
1197  y = nrn_connection_position(csec);
1198  if (x == y) {
1199  return false;
1200  }
1201  x = y;
1202  break;
1203  case 2:
1204  return false;
1205  }
1206  }
1207  return true;
1208 }
1209 
1210 void ShapeScene::color(Section* sec1, Section* sec2, const Color* c) {
1211  nrn_clear_mark();
1212  Section* sec;
1213  for (sec = sec1; sec; sec = nrn_trueparent(sec)) {
1215  }
1216  for (sec = sec2; sec; sec = nrn_trueparent(sec)) {
1218  }
1219  GlyphIndex i, cnt = sg_->count();
1220  for (i = 0; i < cnt; ++i) {
1221  ShapeSection* ss = (ShapeSection*) sg_->component(i);
1222  if (ss->good()) {
1223  switch (nrn_value_mark(ss->section())) {
1224  case 1:
1225  ss->setColor(c, this);
1226  break;
1227  case 2:
1228  if (par_helper(ss->section())) {
1229  ss->setColor(c, this);
1230  }
1231  break;
1232  }
1233  }
1234  }
1235 }
1236 
1237 void ShapeScene::colorseg(Section* sec, double x, const Color* c) {
1239  if (ss && ss->color() != c) {
1240  ss->setColorseg(c, x, this);
1241  }
1242 }
1243 
1244 void ShapeScene::color(Section* sec, const Color* c) {
1246  if (ss && ss->color() != c) {
1247  ss->setColor(c, this);
1248  }
1249 }
1250 
1251 void ShapeScene::color(const Color* c) {
1252  GlyphIndex i, cnt = sg_->count();
1253  for (i = 0; i < cnt; ++i) {
1254  ShapeSection* ss = (ShapeSection*) sg_->component(i);
1255  if (ss->color() != c && ss->good()) {
1256  ss->setColor(c, this);
1257  }
1258  }
1259 }
1260 
1261 void ShapeScene::color(SectionList* sl, const Color* c) {
1262  Resource::ref(sl);
1263  nrn_clear_mark();
1264  for (Section* sec = sl->begin(); sec; sec = sl->next()) {
1266  }
1267  GlyphIndex i, cnt = sg_->count();
1268  for (i = 0; i < cnt; ++i) {
1269  ShapeSection* ss = (ShapeSection*) sg_->component(i);
1270  if (ss->color() != c && ss->good() && nrn_value_mark(ss->section())) {
1271  ss->setColor(c, this);
1272  }
1273  }
1275 }
1276 
1277 void ShapeScene::view(Coord) {
1278  ShapeView* v = new ShapeView(this);
1279  ViewWindow* w = new ViewWindow(v, "Shape");
1280  w->map();
1281 }
1282 
1283 void ShapeScene::view(Coord* x) {
1284  ShapeView* v = new ShapeView(this, x);
1285  ViewWindow* w = new ViewWindow(v, "Shape");
1286  w->xplace(int(x[4]), int(x[5]));
1287  w->map();
1288 }
1289 
1291  return selected_;
1292 }
1293 
1295  selected_ = s;
1296  x_sel_ = x;
1297  y_sel_ = y;
1298 }
1299 
1300 float ShapeScene::arc_selected() {
1301  if (!selected() || x_sel_ == fil) {
1302  return .5;
1303  }
1304  return selected()->arc_position(x_sel_, y_sel_);
1305 }
1306 
1308  sec_ = sec;
1309  section_ref(sec_);
1311  color_->ref();
1312  old_ = NULL;
1313  pvar_ = NULL;
1314  colorseg_ = NULL;
1315  colorseg_size_ = 0;
1316  scale(1.);
1317 
1318  if (sec_->npt3d == 0) {
1319  nrn_define_shape();
1320  }
1321  n_ = sec_->npt3d;
1322  assert(n_);
1323  x_ = new float[n_];
1324  y_ = new float[n_];
1325  // Rotation3d rot;
1326  // transform3d(&rot);
1327 }
1328 
1330  color_->unref();
1331  int n = sec_->npt3d - 1;
1332  delete[] x_;
1333  delete[] y_;
1334  clear_variable();
1336 }
1337 
1339  int i;
1340  if (!good()) {
1341  return;
1342  }
1343  if (n_ != sec_->npt3d) {
1344  if (sec_->npt3d == 0) {
1345  nrn_define_shape();
1346  }
1347  n_ = sec_->npt3d;
1348  delete[] x_;
1349  delete[] y_;
1350  x_ = new float[n_];
1351  y_ = new float[n_];
1352  }
1353  float r[3];
1354  Coord x0, y0, xp, yp;
1355  r[0] = sec_->pt3d[0].x;
1356  r[1] = sec_->pt3d[0].y;
1357  r[2] = sec_->pt3d[0].z;
1358  rot->rotate(r, r);
1359  xp = x0 = r[0];
1360  yp = y0 = r[1];
1361 
1362  // needed for len_scale since each section has to be translated to
1363  // its connection point
1364  Section* ps = nrn_trueparent(sec_);
1365  if (ps && ps->volatile_ptr) {
1366  ShapeSection* pss = (ShapeSection*) ps->volatile_ptr;
1367  // need the connection position relative to the trueparent
1368  Section* sec;
1369  for (sec = sec_; sec->parentsec != ps; sec = sec->parentsec) {
1370  ;
1371  }
1372  pss->loc(nrn_connection_position(sec), xp, yp);
1373  }
1374  // but need to deal with the logical_connection which may exist
1375  // on any section between sec and trueparent. Just hope there is
1376  // no more than one.
1377  Coord xinc = 0;
1378  Coord yinc = 0;
1379  Pt3d* logic_con = NULL;
1380  if (ps) {
1381  for (Section* sec = sec_; sec != ps; sec = sec->parentsec) {
1382  logic_con = sec->logical_connection;
1383  if (logic_con) {
1384  break;
1385  }
1386  }
1387  }
1388  if (logic_con) {
1389  r[0] = logic_con->x;
1390  r[1] = logic_con->y;
1391  r[2] = logic_con->z;
1392  rot->rotate(r, r);
1393  xinc = x0 - r[0];
1394  yinc = y0 - r[1];
1395  }
1396  xp += xinc;
1397  yp += yinc;
1398 
1399  for (i = 0; i < n_; ++i) {
1400  r[0] = sec_->pt3d[i].x;
1401  r[1] = sec_->pt3d[i].y;
1402  r[2] = sec_->pt3d[i].z;
1403  rot->rotate(r, r);
1404  x_[i] = xp + len_scale_ * (r[0] - x0); // *100./(100. - r[2]);
1405  y_[i] = yp + len_scale_ * (r[1] - y0); // *100./(100. - r[2]);
1406  }
1407  Coord x = x_[0];
1408  Coord y = y_[0];
1409  Coord d2 = Math::abs(sec_->pt3d[0].d) / 2 + 1;
1410 
1411  xmin_ = x - d2;
1412  xmax_ = x + d2;
1413  ymin_ = y - d2;
1414  ymax_ = y + d2;
1415 
1416  for (i = 1; i < n_; i++) {
1417  x = x_[i];
1418  y = y_[i];
1419  d2 = Math::abs(sec_->pt3d[i].d) / 2 + 1;
1420 
1421  xmin_ = Math::min(xmin_, x - d2);
1422  xmax_ = Math::max(xmax_, x + d2);
1423  ymin_ = Math::min(ymin_, y - d2);
1424  ymax_ = Math::max(ymax_, y + d2);
1425  }
1426 }
1427 
1428 void ShapeSection::loc(double arc, Coord& x, Coord& y) {
1429  double a = arc0at0(sec_) ? arc : 1. - arc;
1430  double len = section_length(sec_);
1431  int i;
1432  if (a <= .0001) {
1433  i = 0;
1434  } else if (a >= .999) {
1435  i = sec_->npt3d - 1;
1436  } else {
1437  a *= len;
1438  for (i = 1; i < sec_->npt3d; ++i) {
1439 #if 0
1440  // the nearest 3-d point
1441  if (a < (sec_->pt3d[i].arc + sec_->pt3d[i-1].arc)) {
1442  break;
1443  }
1444 #else
1445  // above is not good if 3-d points are far apart and not near center of
1446  // a segment. So return the location at the center of the segment.
1447  if (a <= sec_->pt3d[i].arc) {
1448  float a1 = sec_->pt3d[i - 1].arc;
1449  float a2 = sec_->pt3d[i].arc;
1450  if (a2 > a1) {
1451  float t1 = (a - a1) / (a2 - a1);
1452  x = x_[i] * t1 + x_[i - 1] * (1. - t1);
1453  y = y_[i] * t1 + y_[i - 1] * (1. - t1);
1454  return;
1455  } else {
1456  break;
1457  }
1458  }
1459 #endif
1460  }
1461  i -= 1;
1462  }
1463  x = x_[i];
1464  y = y_[i];
1465 }
1466 
1467 #if 0
1470  printf("update %d %d\n", secname(section()), t->flags());
1471  if (t->test(TelltaleState::is_enabled_active)) {
1472  setColor(sec_sel_color());
1474  }else if (t->test(TelltaleState::is_enabled)) {
1475  if (color_ == sec_sel_color()) {
1476 //printf("setting to dark\n");
1478  }
1480  }
1481 }
1482 #endif
1483 
1484 void ShapeSection::request(Requisition& req) const {
1485  // Requirement rx(xmax_ - xmin_, 0, 0, -xmin_/(xmax_ - xmin_));
1486  // Requirement ry(ymax_ - ymin_, 0, 0, -ymin_/(ymax_ - ymin_));
1487 
1490  req.require(Dimension_X, rx);
1491  req.require(Dimension_Y, ry);
1492 }
1493 
1494 void ShapeSection::size(Coord& l, Coord& b, Coord& r, Coord& t) const {
1495  l = xmin_;
1496  r = xmax_;
1497  b = ymin_;
1498  t = ymax_;
1499 }
1500 
1501 void ShapeSection::allocate(Canvas* c, const Allocation& a, Extension& ext) {
1502  ext.set(c, a);
1503  // Coord x = a.x();
1504  // Coord y = a.y();
1505  // ext.merge_xy(c, x + xmin_, x + xmax_, y + ymin_, y + ymax_);
1506  // ext.set_xy(c, xmin_, xmax_, ymin_, ymax_);
1507 }
1508 
1509 void ShapeSection::selectMenu() { // popup menu item selected
1510  const char* name = secname(sec_);
1511  printf("%s\n", name);
1512  Color* blue = (Color*) Color::lookup(Session::instance()->default_display(), "blue");
1514  setColor(blue, s);
1515  s->selected(this);
1516  Oc oc;
1517  hoc_ivpanel(name);
1518  char buf[200];
1519  hoc_ivmenu(name);
1520  sprintf(buf, "%s nrnsecmenu(.5, 1)", name);
1521  hoc_ivbutton("Parameters", buf);
1522  sprintf(buf, "%s nrnsecmenu(.5, 2)", name);
1523  hoc_ivbutton("Assigned", buf);
1524  sprintf(buf, "%s nrnsecmenu(.5, 3)", name);
1525  hoc_ivbutton("States", buf);
1526  hoc_ivmenu(0);
1527  hoc_ivpanel(0);
1528 }
1529 
1530 Section* ShapeSection::section() const {
1531  return sec_;
1532 }
1533 
1534 bool ShapeSection::good() const {
1535  return sec_->prop != 0;
1536 }
1537 
1539  if (!pvar_) {
1540  return;
1541  }
1542  int i, n = section()->nnode - 1;
1543  for (i = 0; i < n; ++i) {
1544  pvar_[i] = nrn_recalc_ptr(pvar_[i]);
1545  }
1546 }
1547 
1549  clear_variable();
1550  if (!good()) {
1551  return;
1552  }
1553  int i, n = section()->nnode - 1;
1554  pvar_ = new double*[n];
1555  old_ = new const Color*[n];
1556  bool any = false;
1557  if (nrn_exists(sym, section()->pnode[0])) {
1558  for (i = 0; i < n; ++i) {
1559  pvar_[i] =
1561  old_[i] = NULL;
1562  if (pvar_[i]) {
1563  any = true;
1564  }
1565  }
1566  } else {
1567  for (i = 0; i < n; ++i) {
1568  pvar_[i] = 0;
1569  old_[i] = NULL;
1570  }
1571  }
1572 }
1574  if (pvar_) {
1575  delete[] pvar_;
1576  pvar_ = NULL;
1577  }
1578  if (old_) {
1579  delete[] old_;
1580  old_ = NULL;
1581  }
1582  if (colorseg_) {
1583  for (int i = 0; i < colorseg_size_; ++i) {
1584  colorseg_[i]->unref();
1585  }
1586  delete[] colorseg_;
1587  colorseg_ = NULL;
1588  colorseg_size_ = 0;
1589  }
1590 }
1591 void ShapeSection::draw(Canvas* c, const Allocation& a) const {
1592  if (!good()) {
1593  return;
1594  }
1595  float e = 1e-2;
1596 #if 0
1597 // fails when length very long > 100000. If checking important
1598 // then should use relative comparison
1599  if (!(
1600  Math::equal(xmin_, a.left(), e) &&
1601  Math::equal(xmax_, a.right(), e) &&
1602  Math::equal(ymin_, a.bottom(), e) &&
1603  Math::equal(ymax_, a.top(), e)
1604  )) {
1605 printf("xmin_=%g a.left=%g ymin_=%g a.bottom=%g xmax_=%g a.right=%g\n",
1606 xmin_, a.left(),ymin_,a.bottom(),xmax_,a.right());
1607  }
1608 #endif
1609  Coord x = a.x(), y = a.y();
1610  fast_draw(c, x, y, true);
1611 }
1612 
1613 void ShapeSection::fast_draw(Canvas* c, Coord x, Coord y, bool b) const {
1614  Section* sec = section();
1615  IfIdraw(pict());
1616  if (pvar_ || (colorseg_ && colorseg_size_ == sec_->nnode - 1)) {
1617  const Color* color;
1618  ColorValue* cv;
1619  if (pvar_) {
1621  }
1622  if (sec->nnode == 2) {
1623  if (colorseg_) {
1624  color = colorseg_[0];
1625  } else {
1626  if (pvar_[0]) {
1627  color = cv->get_color(*pvar_[0]);
1628  } else {
1629  color = cv->no_value();
1630  }
1631  if (color != old_[0] || b) {
1632  b = true;
1633  ((ShapeSection*) this)->old_[0] = color;
1634  }
1635  }
1636  if (b) {
1637  draw_points(c, color, 0, sec_->npt3d);
1638  }
1639 ///////////////////////////////////////
1640 #if FASTIDIOUS
1641  } else if (sec->npt3d > 2) {
1642  // draw each segment with proper color such that segment boundaries are
1643  // at least within 5% of their proper location and best possible relative to
1644  // actual points. i.e. if a section boundary is between 3d points such that
1645  // moving the boundary to the nearest point increases or decreases the
1646  // length of the segment by more than 5%, then draw the fractional
1647  // interval. Otherwise move the boundary to the nearest point.
1648 
1649  int iseg, i3d;
1650  double xbegin; // end location already drawn
1651  double xend; // location we'd like to draw to
1652  double dseg; // accurate desired length of segment
1653  double a3dold; // the arc length at i3d-1
1654  double a3dnew; // the arc length at i3d
1655  double frac; // fraction of a segment length of the a3dnew point from
1656  // xend when a3dnew > xend
1657 
1658  // walk iseg=0 through sec->nnode-2
1659  // note that a3d points are totally arbitrary but segments are
1660  // all approximately dseg in length.
1661  // we don't want to draw anything < .05*dseg in length unless it is
1662  // a complete a3d interval. We might draw something up to 1.1*dseg in length.
1663  dseg = section_length(sec_) / double(sec_->nnode - 1);
1664  xbegin = 0.;
1665  a3dold = 0.;
1666  i3d = 1;
1667  for (iseg = 0; iseg < sec->nnode - 1; ++iseg) {
1668  if (colorseg_) {
1669  color = colorseg_[iseg];
1670  } else {
1671  if (pvar_[iseg]) {
1672  color = cv->get_color(*pvar_[iseg]);
1673  } else {
1674  color = cv->no_value();
1675  }
1676  if (color != old_[iseg] || b) {
1677  ((ShapeSection*) this)->old_[iseg] = color;
1678  b = true;
1679  }
1680  }
1681  xend = double(iseg + 1) * dseg;
1682  for (; i3d < sec->npt3d; ++i3d) {
1683  a3dold = sec_->pt3d[i3d - 1].arc;
1684  a3dnew = sec_->pt3d[i3d].arc;
1685  if (a3dnew > xend) {
1686  frac = (a3dnew - xend) / dseg;
1687  // do we move to a3dnew or
1688  // actually draw the fractional line
1689  if (frac < .05) { // draw to a3dnew
1690  fastidious_draw(c, color, i3d, xbegin, a3dnew);
1691  xbegin = a3dnew;
1692  ++i3d;
1693  break; // on to next segment
1694  // and next i3d
1695  } else { // draw to xend
1696  fastidious_draw(c, color, i3d, xbegin, xend);
1697  xbegin = xend;
1698  break; // on to next segment
1699  // and reread i3d
1700  }
1701  } else { // draw from xbegin to a3dnew
1702  fastidious_draw(c, color, i3d, xbegin, a3dnew);
1703  xbegin = a3dnew;
1704  }
1705  }
1706  }
1707  assert(Math::equal(xend, sec_->pt3d[sec_->npt3d - 1].arc, 1e-6));
1708 #endif // FASTIDIOUS
1709  ///////////////////////////////////////
1710  } else {
1711  for (int iseg = 0; iseg < sec->nnode - 1; ++iseg) {
1712  if (colorseg_) {
1713  color = colorseg_[iseg];
1714  } else {
1715  if (pvar_[iseg]) {
1716  color = cv->get_color(*pvar_[iseg]);
1717  } else {
1718  color = cv->no_value();
1719  }
1720  if (color != old_[iseg] || b) {
1721  ((ShapeSection*) this)->old_[iseg] = color;
1722  b = true;
1723  }
1724  }
1725  if (b) {
1726  draw_seg(c, color, iseg);
1727  }
1728  }
1729  }
1730  } else {
1731  draw_points(c, color_, 0, sec_->npt3d);
1732  }
1733  IfIdraw(end());
1734 }
1735 
1736 #if FASTIDIOUS
1738  const Color* color,
1739  int i1,
1740  float a1,
1741  float a2) const {
1742  int i;
1743  float len, f1, f2, d, x1, x2, y1, y2, a, aa;
1744  if (!color) {
1745  return;
1746  }
1747  i = i1 - 1;
1748  a = sec_->pt3d[i].arc;
1749  aa = sec_->pt3d[i1].arc;
1750  if ((aa - a) < 1e-5) {
1751  return;
1752  }
1753  f1 = (a1 - a) / (aa - a);
1754  f2 = (a2 - a) / (aa - a);
1755  d = x_[i1] - x_[i];
1756  x1 = f1 * d + x_[i];
1757  x2 = f2 * d + x_[i];
1758  d = y_[i1] - y_[i];
1759  y1 = f1 * d + y_[i];
1760  y2 = f2 * d + y_[i];
1762  case ShapeScene::show_diam:
1763  float d1, d2, t1, t2;
1764  t1 = Math::abs(sec_->pt3d[i].d) / 2.;
1765  t2 = Math::abs(sec_->pt3d[i1].d) / 2.;
1766  d1 = f1 * (t2 - t1) + t1;
1767  d2 = f2 * (t2 - t1) + t1;
1768  trapezoid(c, color, x1, y1, x2, y2, d1, d2);
1769  if (beveljoin_) {
1770  if (f1 < 1e-6) {
1771  bevel_join(c, color, i, t1);
1772  }
1773  }
1774  break;
1777  c->new_path();
1778  c->move_to(x1, y1);
1779  c->line_to(x2, y2);
1780  c->stroke(color, brushes->brush(0));
1781  IfIdraw(line(c, x1, y1, x2, y2, color));
1782  break;
1783  }
1784 }
1785 
1786 #endif
1787 
1788 #if BEVELJOIN
1789 void ShapeSection::bevel_join(Canvas* c, const Color* color, int i, float d) const {
1790  if (i == 0) {
1791  return;
1792  }
1793  float perp1[2], perp2[2], x, y;
1794  x = x_[i];
1795  y = y_[i];
1796  bool b = true;
1797  b &= MyMath::unit_normal(x - x_[i - 1], y - y_[i - 1], perp1);
1798  b &= MyMath::unit_normal(x_[i + 1] - x, y_[i + 1] - y, perp2);
1799  if (b && (perp1[0] != perp2[0] || perp1[1] != perp2[1])) {
1800  Coord xt[4], yt[4];
1801  xt[0] = x + d * perp1[0];
1802  yt[0] = y + d * perp1[1];
1803  xt[1] = x - d * perp2[0];
1804  yt[1] = y - d * perp2[1];
1805  xt[2] = x - d * perp1[0];
1806  yt[2] = y - d * perp1[1];
1807  xt[3] = x + d * perp2[0];
1808  yt[3] = y + d * perp2[1];
1809  int i;
1810  c->new_path();
1811  c->move_to(xt[0], yt[0]);
1812  for (i = 1; i < 4; ++i) {
1813  c->line_to(xt[i], yt[i]);
1814  }
1815  c->close_path();
1816  c->fill(color);
1817  if (OcIdraw::idraw_stream) {
1818  OcIdraw::polygon(c, 4, xt, yt, color, 0, true);
1819  }
1820  }
1821 }
1822 #else
1823 void ShapeSection::bevel_join(Canvas*, const Color*, int, float) const {}
1824 #endif
1825 
1826 void ShapeSection::draw_seg(Canvas* c, const Color* color, int iseg) const {
1827  float darc = 1. / float(sec_->nnode - 1);
1828  float ds = darc * section_length(sec_);
1829  float x = ds * iseg;
1830  int i, j;
1831  if (sec_->nnode == 2) {
1832  i = 0;
1833  j = sec_->npt3d;
1834  draw_points(c, color, i, j);
1835  } else if (sec_->npt3d == 2) {
1836  float x1, x2, y1, y2;
1837  x1 = darc * iseg * (x_[1] - x_[0]) + x_[0];
1838  x2 = darc * (iseg + 1) * (x_[1] - x_[0]) + x_[0];
1839  y1 = darc * iseg * (y_[1] - y_[0]) + y_[0];
1840  y2 = darc * (iseg + 1) * (y_[1] - y_[0]) + y_[0];
1842  case ShapeScene::show_diam:
1843  float d1, d2, t1, t2;
1844  t1 = Math::abs(sec_->pt3d[0].d) / 2.;
1845  t2 = Math::abs(sec_->pt3d[1].d) / 2.;
1846  d1 = darc * iseg * (t2 - t1) + t1;
1847  d2 = darc * (iseg + 1) * (t2 - t1) + t1;
1848  trapezoid(c, color, x1, y1, x2, y2, d1, d2);
1849  break;
1852  c->new_path();
1853  c->move_to(x1, y1);
1854  c->line_to(x2, y2);
1855  c->stroke(color, brushes->brush(0));
1856  IfIdraw(line(c, x1, y1, x2, y2, color));
1857  break;
1858  }
1859  } else {
1860  for (i = 1; i < sec_->npt3d; i++) {
1861  if (sec_->pt3d[i].arc > x) {
1862  break;
1863  }
1864  }
1865  i--;
1866  x += ds * 1.0001;
1867  for (j = i + 1; j < sec_->npt3d; j++) {
1868  if (sec_->pt3d[j].arc > x) {
1869  break;
1870  }
1871  }
1872  draw_points(c, color, i, j);
1873  }
1874 }
1875 
1876 void ShapeSection::draw_points(Canvas* c, const Color* color, int i, int j) const {
1877  switch (ShapeScene::current_draw_scene()->shape_type()) {
1878  case ShapeScene::show_diam:
1879  while (++i < j) {
1880  trapezoid(c, color, i);
1881 #if BEVELJOIN
1882  if (beveljoin_) {
1883  bevel_join(c, color, i - 1, Math::abs(sec_->pt3d[i - 1].d) / 2);
1884  }
1885 #endif
1886  }
1887  break;
1889  IfIdraw(mline(c, j - i, x_ + i, y_ + i, color));
1890  c->new_path();
1891  c->move_to(x_[i], y_[i]);
1892  while (++i < j) {
1893  c->line_to(x_[i], y_[i]);
1894  }
1895  c->stroke(color, brushes->brush(0));
1896  break;
1898  IfIdraw(line(c, x_[i], y_[i], x_[j - 1], y_[j - 1], color));
1899  c->new_path();
1900  c->line(x_[i], y_[i], x_[j - 1], y_[j - 1], color, 0);
1901  break;
1902  }
1903 }
1904 
1905 void ShapeSection::trapezoid(Canvas* c, const Color* color, int i) const {
1906  trapezoid(c,
1907  color,
1908  x_[i - 1],
1909  y_[i - 1],
1910  x_[i],
1911  y_[i],
1912  Math::abs(sec_->pt3d[i - 1].d) / 2.,
1913  Math::abs(sec_->pt3d[i].d) / 2.);
1914 }
1915 
1917  const Color* color,
1918  float x1,
1919  float y1,
1920  float x2,
1921  float y2,
1922  float d1,
1923  float d2) const {
1924  float x, y, rx, ry, d, norm;
1925  x = x2 - x1;
1926  y = y2 - y1;
1927  norm = sqrt(x * x + y * y);
1928 
1929  if (norm > .0001) {
1930  rx = y / norm;
1931  ry = -x / norm;
1932  } else {
1933  return;
1934  }
1935 
1936  d = d1;
1937  c->new_path();
1938  c->move_to(x1 + rx * d, y1 + ry * d);
1939  c->line_to(x1 - rx * d, y1 - ry * d);
1940  d = d2;
1941  c->line_to(x2 - rx * d, y2 - ry * d);
1942  c->line_to(x2 + rx * d, y2 + ry * d);
1943  c->close_path();
1944  c->fill(color);
1945  if (OcIdraw::idraw_stream) {
1946  Coord xt[4], yt[4];
1947  d = d1;
1948  xt[0] = x1 + rx * d;
1949  yt[0] = y1 + ry * d;
1950  xt[1] = x1 - rx * d;
1951  yt[1] = y1 - ry * d;
1952  d = d2;
1953  xt[2] = x2 - rx * d;
1954  yt[2] = y2 - ry * d;
1955  xt[3] = x2 + rx * d;
1956  yt[3] = y2 + ry * d;
1957  OcIdraw::polygon(c, 4, xt, yt, color, 0, true);
1958  }
1959 }
1960 
1961 void ShapeSection::setColorseg(const Color* color, double x, ShapeScene* s) {
1962  if (x <= 0.0 || x >= 1.0) {
1963  return;
1964  }
1965  if (colorseg_size_ != sec_->nnode - 1) {
1966  clear_variable();
1967  }
1968  if (!colorseg_) {
1969  colorseg_size_ = sec_->nnode - 1;
1970  colorseg_ = new const Color*[colorseg_size_];
1971  for (int i = 0; i < colorseg_size_; ++i) {
1972  colorseg_[i] = color_;
1973  color_->ref();
1974  }
1975  }
1976  int i = int(x * colorseg_size_);
1977  color->ref();
1978  colorseg_[i]->unref();
1979  colorseg_[i] = color;
1980  damage(s);
1981 }
1982 
1983 void ShapeSection::setColor(const Color* color, ShapeScene* s) {
1984  clear_variable();
1985  color->ref();
1986  color_->unref();
1987  color_ = color;
1988  damage(s);
1989 }
1990 
1991 void ShapeSection::pick(Canvas*, const Allocation&, int depth, Hit& h) {
1992  if (!good() || !h.event() || h.event()->type() != Event::down)
1993  return;
1994  Coord x = h.left();
1995  Coord y = h.bottom();
1996  if (!near_section(x, y, XYView::current_pick_view()->x_pick_epsilon()))
1997  return;
1998  if (h.event()->pointer_button() == Event::left) {
2000  // printf("section %s x=%g y=%g\n", secname(sec_), x, y);
2001  if (h.any()) { // maybe one already found is closer
2002  Coord x2 = how_near(x, y);
2003  if (s->selected()) {
2004  Coord x1 = s->selected()->how_near(x, y);
2005  // printf("%s at %g and %s at %g\n", secname(s->selected()->section()), x1,
2006  // secname(section()), x2);
2007  if (x1 < x2) {
2008  return;
2009  }
2010  }
2011  }
2012  s->selected(this, x, y);
2013  if (s->section_handler()) {
2014  h.target(depth, this, 0, (s->section_handler(this)));
2015  }
2016  }
2017 }
2018 
2021 }
2022 
2025 }
2026 
2027 bool ShapeSection::near_section(Coord x, Coord y, Coord mineps) const {
2028  int n = sec_->npt3d;
2029  for (int i = 1; i < n; ++i) {
2031  y,
2032  x_[i - 1],
2033  y_[i - 1],
2034  x_[i],
2035  y_[i],
2036  Math::max(float(Math::abs(sec_->pt3d[i - 1].d) / 2.),
2037  float(mineps)))) {
2038  return true;
2039  }
2040  }
2041  return false;
2042 }
2043 
2044 float ShapeSection::how_near(Coord x, Coord y) const {
2045  int n = sec_->npt3d;
2046  float d2, d = 1e20;
2047  for (int i = 1; i < n; ++i) {
2048  d2 = MyMath::distance_to_line_segment(x, y, x_[i - 1], y_[i - 1], x_[i], y_[i]);
2049  if (d2 < d) {
2050  d = d2;
2051  }
2052  }
2053  return d;
2054 }
2055 
2056 float ShapeSection::arc_position(Coord x, Coord y) const {
2057  int ic, n = sec_->npt3d;
2058  float d2, d = 1e20;
2059  float darc, len, dlen1;
2060  for (int i = 1; i < n; ++i) {
2061  d2 = MyMath::distance_to_line_segment(x, y, x_[i - 1], y_[i - 1], x_[i], y_[i]);
2062  if (d2 < d) {
2063  d = d2;
2064  ic = i - 1;
2065  }
2066  }
2067 
2068  d *= d;
2069  len = MyMath::norm2(x_[ic] - x_[ic + 1], y_[ic] - y_[ic + 1]);
2070  dlen1 = MyMath::norm2(x - x_[ic], y - y_[ic]);
2071  if (dlen1 <= d + 1e-2) {
2072  darc = 0.;
2073  } else if (len <= d + 1e-2) {
2074  darc = sqrt(len);
2075  } else {
2076  darc = sqrt(dlen1 - d);
2077  }
2078 
2079  d = sec_->pt3d[ic].arc + darc;
2080  d /= section_length(sec_);
2081  d = (d < 0.) ? 0. : d;
2082  d = (d > 1.) ? 1. : d;
2083  d = (nrn_section_orientation(sec_) == 1.) ? 1. - d : d;
2084  // round to nearest segment point
2085  float dx = 1. / (sec_->nnode - 1);
2086  if (d < dx / 4.) {
2087  d = 0.;
2088  } else if (d > 1. - dx / 4.) {
2089  d = 1.;
2090  } else {
2091  d = (int(d * (sec_->nnode - 1)) + .5) * dx;
2092  }
2093  return d;
2094 }
2095 
2096 int ShapeSection::get_coord(double a, Coord& x, Coord& y) const {
2097  int i, n = sec_->npt3d;
2098  double arc = (nrn_section_orientation(sec_) == 1.) ? (1. - a) : a;
2099  arc *= section_length(sec_);
2100  for (i = 0; i < n; ++i) {
2101  if (arc < sec_->pt3d[i].arc) {
2102  break;
2103  }
2104  }
2105  if (i == n) {
2106  i -= 1;
2107  x = x_[i];
2108  y = y_[i];
2109  } else {
2110  double frac = (arc - sec_->pt3d[i - 1].arc) / (sec_->pt3d[i].arc - sec_->pt3d[i - 1].arc);
2111  x = x_[i - 1] * (1 - frac) + x_[i] * frac;
2112  y = y_[i - 1] * (1 - frac) + y_[i] * frac;
2113  i = (i > 0 && frac < .5) ? i - 1 : i;
2114  }
2115  return i;
2116 }
2117 
2119  // printf("ShapeSection::damage %s\n", secname(sec_));
2120  s->damage(xmin_, ymin_, xmax_, ymax_);
2121 }
2122 
2124  ss_ = NULL;
2125 }
2128 }
2130  return true;
2131 }
2133  Resource::ref(ss);
2135  ss_ = ss;
2136 }
2138  return ss_;
2139 }
2140 
2141 PointMark::PointMark(OcShape* sh, Object* ob, const Color* c, const char style, const float size)
2142  : MonoGlyph(NULL) {
2143  sh_ = sh; // don't ref
2144  ob_ = ob;
2145  if (ob_) {
2146  ObjObservable::Attach(ob, this);
2147  }
2148  body(HocMark::instance(style, size, c, NULL));
2149  i_ = 0;
2150  sec_ = NULL;
2151  xloc_ = 0.;
2152 }
2153 PointMark::~PointMark() {
2154  // printf("~PointMark\n");
2155  if (ob_) {
2156  Object* ob = ob_;
2157  ob_ = NULL;
2158  // printf("Detach\n");
2159  ObjObservable::Detach(ob, this);
2160  }
2161 }
2163  // printf("PointMark::disconnect\n");
2164  if (ob_) {
2165  Object* ob = ob_;
2166  ob_ = NULL;
2167  // printf("point_mark_remove\n");
2168  sh_->point_mark_remove(ob);
2169  }
2170 }
2172  everything_ok();
2173 }
2174 
2175 void PointMark::draw(Canvas* c, const Allocation& a0) const {
2176  const Transformer& tv = XYView::current_draw_view()->s2o();
2177  Allocation a(a0);
2178  Coord x, y;
2179  tv.inverse_transform(x_, y_, x, y);
2180  a.x_allotment().origin(x);
2181  a.y_allotment().origin(y);
2182  MonoGlyph::draw(c, a);
2183 }
2184 
2185 void PointMark::set_loc(Section* sec, float x) {
2186  sec_ = sec;
2187  xloc_ = x;
2188 }
2189 
2190 bool PointMark::everything_ok() {
2191  sec_ = NULL;
2192  if (ob_) {
2193  Point_process* pnt = ob2pntproc_0(ob_);
2194  if (pnt && pnt->sec) {
2195  sec_ = pnt->sec;
2196  xloc_ = nrn_arc_position(pnt->sec, pnt->node);
2197  }
2198  }
2199  if (!sec_ || !sec_->prop) {
2200  return false;
2201  }
2202  ShapeSection* ss = sh_->shape_section(sec_);
2203  if (!ss) {
2204  return false;
2205  }
2206  ss->get_coord(xloc_, x_, y_);
2207  if (i_ >= sh_->count() || sh_->component(i_) != (Glyph*) this) {
2208  i_ = sh_->glyph_index(this);
2209  }
2210  if (i_ < 0)
2211  return false;
2212  sh_->move(i_, x_, y_);
2213 
2214  return true;
2215 }
2216 
2217 void OcShape::transform3d(Rubberband* rot) {
2219  if (point_mark_list_) {
2220  GlyphIndex i, cnt = point_mark_list_->count();
2221  for (i = 0; i < cnt; ++i) {
2222  ((PointMark*) point_mark_list_->component(i))->update(NULL);
2223  }
2224  }
2225 }
2226 
2227 ShapeChangeObserver::ShapeChangeObserver(ShapeScene* s) {
2228  s_ = s; // do not ref
2229  shape_changed_ = nrn_shape_changed_;
2230  struc_changed_ = structure_change_cnt;
2231  Oc oc;
2232  oc.notify_attach(this);
2233 }
2234 ShapeChangeObserver::~ShapeChangeObserver() {
2235  Oc oc;
2236  oc.notify_detach(this);
2237 }
2239  if (shape_changed_ != nrn_shape_changed_) {
2240  // printf("ShapeChangeObserver::update shape_changed%p nrn_shape_changed=%d\n", this,
2241  // nrn_shape_changed_);
2242  shape_changed_ = nrn_shape_changed_;
2243  nrn_define_shape();
2244  volatile_ptr_ref = NULL;
2245  if (struc_changed_ != structure_change_cnt) {
2246  struc_changed_ = structure_change_cnt;
2247  // printf("ShapeChangeObserver::update structure_changed%p\n", this);
2248  if (s_->view_all()) {
2249  s_->observe();
2250  }
2251  shape_changed_ = 0;
2252  } else {
2253  s_->transform3d();
2254  shape_changed_ = nrn_shape_changed_;
2255  s_->flush();
2256  }
2257  }
2258 }
2260  shape_changed_ = 0;
2261 }
2262 #endif // HAVE_IV
#define TelltaleState
Definition: _defines.h:296
#define Color
Definition: _defines.h:74
#define Menu
Definition: _defines.h:176
#define Transformer
Definition: _defines.h:316
#define Canvas
Definition: _defines.h:65
#define Coord
Definition: _defines.h:19
#define Hit
Definition: _defines.h:147
#define Display
Definition: _defines.h:97
#define WidgetKit
Definition: _defines.h:331
#define MonoGlyph
Definition: _defines.h:181
#define GlyphIndex
Definition: _defines.h:23
#define MenuItem
Definition: _defines.h:179
#define Event
Definition: _defines.h:107
#define PolyGlyph
Definition: _defines.h:207
#define Action
Definition: _defines.h:27
#define Glyph
Definition: _defines.h:132
#define CopyString
Definition: _defines.h:2
Section ** secorder
Definition: solve.cpp:77
int section_count
Definition: solve.cpp:76
double nrn_section_orientation(Section *sec)
Definition: cabcode.cpp:1644
const char * secname(Section *sec)
Definition: cabcode.cpp:1776
void nrn_pushsec(Section *sec)
Definition: cabcode.cpp:99
double nrn_arc_position(Section *sec, Node *node)
Definition: cabcode.cpp:1867
Section * nrn_trueparent(Section *sec)
Definition: cabcode.cpp:1666
double section_length(Section *sec)
Definition: cabcode.cpp:387
double nrn_connection_position(Section *sec)
Definition: cabcode.cpp:1639
int nrn_exists(Symbol *s, Node *node)
Definition: cabcode.cpp:1319
void disconnect(void)
Definition: cabcode.cpp:569
int arc0at0(Section *sec)
Definition: cabcode.cpp:399
double * nrn_rangepointer(Section *sec, Symbol *s, double d)
Definition: cabcode.cpp:1335
Section * chk_access(void)
Definition: cabcode.cpp:444
void nrn_popsec(void)
Definition: cabcode.cpp:123
Coord right() const
Definition: geometry.h:293
Coord top() const
Definition: geometry.h:295
Coord x() const
Definition: geometry.h:290
Coord left() const
Definition: geometry.h:292
Coord bottom() const
Definition: geometry.h:294
Coord y() const
Definition: geometry.h:291
const Brush * brush(int) const
const Color * color(int) const
void set(Canvas *, const Allocation &)
Definition: graph.h:57
const Color * color() const
Definition: graph.h:112
virtual GlyphIndex glyph_index(const Glyph *)
virtual void save_phase2(std::ostream &)
virtual void save_phase1(std::ostream &)
virtual void erase_all()
static HocMark * instance(char style, float size, const Color *, const Brush *)
Definition: math.h:71
static bool equal(float x, float y, float e)
Definition: math.h:108
static int abs(int)
Definition: math.cpp:43
static bool near_line_segment(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2, float epsilon)
Definition: mymath.cpp:194
static float distance_to_line_segment(Coord x, Coord y, Coord x1, Coord y1, Coord x2, Coord y2)
Definition: mymath.cpp:165
static bool unit_normal(Coord x, Coord y, Coord *perp)
Definition: mymath.cpp:368
static void round_range(Coord x1, Coord x2, double &y1, double &y2, int &ntic)
Definition: mymath.cpp:276
static void box(Requisition &, Coord &x1, Coord &y1, Coord &x2, Coord &y2)
Definition: mymath.cpp:359
static float norm2(Coord x, Coord y)
Definition: mymath.h:40
static void Detach(Object *, Observer *)
Definition: ocobserv.cpp:27
static void Attach(Object *, Observer *)
Definition: ocobserv.cpp:20
virtual void disconnect(Observable *)
Definition: observe.cpp:87
virtual void update(Observable *)
Definition: observe.cpp:86
Definition: ivoc.h:36
static void help(const char *)
void notify_detach(Observer *)
void notify_attach(Observer *)
static bool helpmode()
Definition: ivoc.h:70
static ostream * idraw_stream
Definition: idraw.h:85
static void polygon(Canvas *, int count, const Coord *x, const Coord *y, const Color *c=NULL, const Brush *b=NULL, bool fill=false)
void xplace(int left, int top)
Definition: ivocmac.cpp:242
virtual void map()
void require(DimensionName, const Requirement &)
virtual void ref() const
Definition: resource.cpp:47
virtual void unref() const
Definition: resource.cpp:52
Rotation3d * rotation()
void origin(float x, float y, float z)
void identity()
void rotate(float x, float y, float z, float *tr) const
void rotate_x(float radians)
void rotate_z(float radians)
void rotate_y(float radians)
virtual bool event(Event &)
virtual Coord y2() const
Definition: scenevie.h:366
virtual Coord y1() const
Definition: scenevie.h:363
virtual void damage(GlyphIndex)
ScenePicker * picker()
virtual void damage_all()
virtual void append(Glyph *)
virtual void new_size(Coord x1, Coord y1, Coord x2, Coord y2)
virtual int tool()
static const Color * default_foreground()
virtual void wholeplot(Coord &x1, Coord &y1, Coord &x2, Coord &y2) const
ScenePicker * picker_
Definition: scenevie.h:337
virtual Coord x2() const
Definition: scenevie.h:360
virtual GlyphIndex count() const
virtual void remove(GlyphIndex)
virtual Coord x1() const
Definition: scenevie.h:357
virtual void help()
virtual void modified(GlyphIndex)
ShapeSection * ss_
Definition: shape.h:180
virtual ~SectionHandler()
ShapeSection * shape_section()
virtual bool event(Event &)
void shape_section(ShapeSection *)
void rotate()
virtual void observe(SectionList *=NULL)
void colorseg(Section *, double, const Color *)
virtual float arc_selected()
virtual void flush()
ColorValue * color_value_
Definition: shape.h:78
void force()
@ SECTION
Definition: shape.h:27
@ ROTATE
Definition: shape.h:27
virtual SectionHandler * section_handler()
virtual float nearest(Coord, Coord)
SectionHandler * section_handler_
Definition: shape.h:80
virtual ShapeSection * selected()
ShapeSection * selected_
Definition: shape.h:76
Coord y_sel_
Definition: shape.h:77
virtual void name(const char *)
virtual ShapeSection * shape_section(Section *)
virtual void wholeplot(Coord &x1, Coord &y1, Coord &x2, Coord &y2) const
static ShapeScene * current_pick_scene()
virtual void save_phase2(std::ostream &)
int shape_type_
Definition: shape.h:79
Rotate3Band * r3b_
Definition: shape.h:82
void shape_type(int)
virtual void view(Coord)
virtual ~ShapeScene()
virtual void transform3d(Rubberband *rb=NULL)
virtual void erase_all()
PolyGlyph * sg_
Definition: shape.h:81
Coord x_sel_
Definition: shape.h:77
int shape_type()
Definition: shape.h:51
ShapeChangeObserver * shape_changed_
Definition: shape.h:84
static ShapeScene * current_draw_scene()
virtual void section_handler(SectionHandler *)
ShapeScene(SectionList *=NULL)
CopyString * var_name_
Definition: shape.h:83
ColorValue * color_value()
@ show_diam
Definition: shape.h:49
@ show_schematic
Definition: shape.h:49
@ show_centroid
Definition: shape.h:49
bool view_all_
Definition: shape.h:75
PolyGlyph * shape_section_list()
virtual void help()
virtual ~ShapeSection()
virtual void draw(Canvas *, const Allocation &) const
virtual void draw_seg(Canvas *, const Color *, int iseg) const
Coord len_scale_
Definition: shape.h:151
Coord * y_
Definition: shape.h:157
virtual void transform3d(Rotation3d *)
Coord xmin_
Definition: shape.h:156
virtual void pick(Canvas *, const Allocation &, int depth, Hit &)
int get_coord(double arc, Coord &, Coord &) const
Coord ymin_
Definition: shape.h:156
bool good() const
Coord * x_
Definition: shape.h:157
Coord ymax_
Definition: shape.h:156
ShapeSection(Section *)
virtual void size(Coord &l, Coord &b, Coord &r, Coord &t) const
Coord xmax_
Definition: shape.h:156
const Color ** old_
Definition: shape.h:153
void bevel_join(Canvas *, const Color *, int, float) const
float arc_position(Coord, Coord) const
const Color * color_
Definition: shape.h:152
virtual void request(Requisition &) const
void fastidious_draw(Canvas *, const Color *, int, float, float) const
Section * sec_
Definition: shape.h:150
const Color ** colorseg_
Definition: shape.h:154
float how_near(Coord, Coord) const
int colorseg_size_
Definition: shape.h:155
void scale(Coord x)
Definition: shape.h:131
int n_
Definition: shape.h:158
Coord scale()
Definition: shape.h:134
virtual void selectMenu()
virtual void clear_variable()
virtual void damage(ShapeScene *)
virtual bool near_section(Coord, Coord, Coord mineps) const
Section * section() const
virtual void allocate(Canvas *, const Allocation &, Extension &)
const Color * color()
Definition: shape.h:113
void update_ptrs()
virtual void fast_draw(Canvas *, Coord x, Coord y, bool) const
virtual void setColorseg(const Color *, double, ShapeScene *)
virtual void draw_points(Canvas *, const Color *, int, int) const
void loc(double, Coord &, Coord &)
double ** pvar_
Definition: shape.h:149
virtual void setColor(const Color *, ShapeScene *)
virtual void set_range_variable(Symbol *)
void trapezoid(Canvas *, const Color *, int i) const
ShapeView(ShapeScene *)
virtual ~ShapeView()
Definition: string.h:34
const char * string() const
Definition: string.h:139
int length() const
Definition: string.h:140
Definition: scenevie.h:203
virtual Scene * scene() const
static XYView * current_draw_view()
static XYView * current_pick_view()
const Transformer & s2o() const
Definition: scenevie.h:139
void execute(Inst *p)
Definition: code.cpp:2661
#define fil
Definition: coord.h:42
Point_process * ob2pntproc(Object *)
Definition: hocmech.cpp:88
int structure_change_cnt
Definition: cvodeobj.cpp:76
double t
Definition: cvodeobj.cpp:59
sprintf(buf, " if (secondorder) {\n" " int _i;\n" " for (_i = 0; _i < %d; ++_i) {\n" " _p[_slist%d[_i]] += dt*_p[_dlist%d[_i]];\n" " }}\n", numeqn, listnum, listnum)
double chkarg(int, double low, double high)
Definition: code2.cpp:638
#define c
static void update(NrnThread *)
Definition: fadvance.cpp:597
@ Dimension_Y
Definition: geometry.h:43
@ Dimension_X
Definition: geometry.h:43
BrushPalette * brushes
ColorPalette * colors
char buf[512]
Definition: init.cpp:13
int hoc_is_object_arg(int narg)
Definition: code.cpp:756
int hoc_is_str_arg(int narg)
Definition: code.cpp:752
double hoc_ac_
Definition: hoc_init.cpp:397
#define TRY_GUI_REDIRECT_ACTUAL_DOUBLE(name, obj)
Definition: gui-redirect.h:71
#define TRY_GUI_REDIRECT_NO_RETURN(name, obj)
Definition: gui-redirect.h:47
#define TRY_GUI_REDIRECT_OBJ(name, obj)
Definition: gui-redirect.h:12
#define TRY_GUI_REDIRECT_ACTUAL_OBJ(name, obj)
Definition: gui-redirect.h:93
#define assert(ex)
Definition: hocassrt.h:32
#define IFGUI
Definition: hocdec.h:372
#define getarg
Definition: hocdec.h:15
#define gargstr
Definition: hocdec.h:14
#define ENDGUI
Definition: hocdec.h:373
#define hocSEC(q)
Definition: hoclist.h:66
Object ** hoc_objgetarg(int)
Definition: code.cpp:1587
#define IfIdraw(arg)
Definition: idraw.h:104
static char line[MAXLINE]
Definition: ivecop.c:35
int ifarg(int)
Definition: code.cpp:1581
Object ** hoc_temp_objptr(Object *)
Definition: code.cpp:216
#define min(a, b)
Definition: matrix.h:157
#define max(a, b)
Definition: matrix.h:154
#define v
Definition: md1redef.h:4
#define sec
Definition: md1redef.h:13
#define i
Definition: md1redef.h:12
#define ITERATE(itm, lst)
Definition: model.h:25
sqrt
Definition: extdef.h:3
force
Definition: extdef.h:5
char * name
Definition: init.cpp:16
#define printf
Definition: mwprefix.h:26
double * nrn_recalc_ptr(double *)
Definition: treeset.cpp:2179
Point_process * ob2pntproc_0(Object *)
Definition: hocmech.cpp:78
Object *(* nrnpy_seg_from_sec_x)(Section *, double)
Definition: netcvode.cpp:123
void nrn_clear_mark(void)
Definition: solve.cpp:459
short nrn_value_mark(Section *)
Definition: solve.cpp:470
void section_ref(Section *)
Definition: solve.cpp:575
void section_unref(Section *)
Definition: solve.cpp:565
void nrn_seg_or_x_arg(int iarg, Section **psec, double *px)
Definition: point.cpp:185
short nrn_increment_mark(Section *)
Definition: solve.cpp:467
int const size_t const size_t n
Definition: nrngsl.h:11
for(i=0;i< n;i++)
size_t j
hoc_List * section_list
Definition: init.cpp:102
void class2oc(const char *, void *(*cons)(Object *), void(*destruct)(void *), Member_func *, int(*checkpoint)(void **), Member_ret_obj_func *, Member_ret_str_func *)
Definition: hoc_oop.cpp:1560
static int component(PyHocObject *po)
Definition: nrnpy_hoc.cpp:445
static N_Vector y_
static N_Vector x_
void hoc_ivbutton(CChar *name, CChar *action, Object *pyact=0)
void hoc_ivmenu(CChar *, bool add2menubar=false)
void hoc_ivpanel(CChar *, bool h=false)
#define xorg
Definition: axis.cpp:156
#define yorg
Definition: axis.cpp:157
static double xinc
Definition: axis.cpp:169
static double yinc
Definition: axis.cpp:169
void recalc_diam()
Definition: treeset.cpp:953
static double remove(void *v)
Definition: ocdeck.cpp:207
#define g
Definition: passive0.cpp:21
#define e
Definition: passive0.cpp:22
static void pnode(Prop *)
Definition: psection.cpp:45
#define left
Definition: rbtqueue.cpp:45
#define color
Definition: rbtqueue.cpp:50
#define lt
Definition: redef.h:91
#define lookup
Definition: redef.h:90
#define implementRubberCallback(T)
Definition: rubband.h:153
#define RubberCallback(T)
Definition: rubband.h:133
#define declareRubberCallback(T)
Definition: rubband.h:138
check_obj_type(o, "SectionList")
sl
Definition: seclist.cpp:181
o
Definition: seclist.cpp:175
static double sh_begin(void *v)
Definition: shape.cpp:218
double nrniv_sh_color_list(void *v)
Definition: shape.cpp:414
static double sh_select(void *v)
Definition: shape.cpp:232
double nrniv_sh_color(void *v)
Definition: shape.cpp:381
double ivoc_gr_menu_action(void *v)
Definition: graph.cpp:329
double nrniv_sh_color_all(void *v)
Definition: shape.cpp:401
static void sh_destruct(void *v)
Definition: shape.cpp:633
static double sh_flush(void *v)
Definition: shape.cpp:209
static double sh_view_count(void *v)
Definition: shape.cpp:256
static double sh_select_action(void *v)
Definition: shape.cpp:242
static double sh_save_name(void *v)
Definition: shape.cpp:223
double(* nrnpy_object_to_double_)(Object *)
Definition: xmenu.cpp:14
static double exec_menu(void *v)
Definition: shape.cpp:494
double ivoc_gr_gif(void *)
Definition: graph.cpp:774
static double sh_point_mark(void *v)
Definition: shape.cpp:427
double ivoc_gr_mark(void *)
Definition: graph.cpp:1027
double ivoc_gr_menu_tool(void *)
Definition: graph.cpp:347
double ivoc_gr_label(void *)
Definition: graph.cpp:862
void Shape_reg()
Definition: shape.cpp:641
Object ** nrniv_sh_nearest_seg(void *v)
Definition: shape.cpp:294
static double sh_printfile(void *v)
Definition: shape.cpp:469
double nrniv_sh_nearest(void *v)
Definition: shape.cpp:267
double nrniv_sh_rotate(void *v)
Definition: shape.cpp:352
Object ** nrniv_sh_selected_seg(void *v)
Definition: shape.cpp:313
static double sh_view(void *v)
Definition: shape.cpp:191
double ivoc_erase_all(void *)
Definition: graph.cpp:763
double ivoc_gr_line(void *)
Definition: graph.cpp:720
double ivoc_gr_erase(void *)
Definition: graph.cpp:752
static double sh_unmap(void *v)
Definition: shape.cpp:370
double ivoc_gr_size(void *)
Definition: graph.cpp:809
double nrniv_sh_observe(void *v)
Definition: shape.cpp:331
static Member_ret_obj_func retobj_members[]
Definition: shape.cpp:598
static void * sh_cons(Object *ho)
Definition: shape.cpp:602
static Member_func sh_members[]
Definition: shape.cpp:531
static double sh_point_mark_remove(void *v)
Definition: shape.cpp:454
double nrniv_sh_push(void *v)
Definition: shape.cpp:278
double nrniv_len_scale(void *v)
Definition: shape.cpp:503
static double sh_show(void *v)
Definition: shape.cpp:480
double ivoc_gr_begin_line(void *)
Definition: graph.cpp:699
int nrn_shape_changed_
Definition: neuron.h:33
#define cnt
Definition: spt2queue.cpp:19
#define NULL
Definition: sptree.h:16
Definition: hocdec.h:227
int refcount
Definition: hocdec.h:228
Section * sec
Definition: section.h:263
Node * node
Definition: section.h:264
Definition: section.h:67
float z
Definition: section.h:68
double arc
Definition: section.h:69
float x
Definition: section.h:68
float y
Definition: section.h:68
float d
Definition: section.h:68
struct Prop * prop
Definition: section.h:63
void * volatile_ptr
Definition: section.h:55
struct Section * child
Definition: section.h:43
short npt3d
Definition: section.h:57
struct Section * parentsec
Definition: section.h:42
struct Section * sibling
Definition: section.h:46
short nnode
Definition: section.h:41
struct Pt3d * pt3d
Definition: section.h:59
Definition: model.h:57
void nrn_define_shape()
Definition: treeset.cpp:1419