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