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