SheafSystem  0.0.0.0
vtk_poly_data_builder.cc
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 
18 // Implementation for class vtk_poly_data_builder
19 
20 #include "SheafSystem/vtk_poly_data_builder.h"
21 #include "SheafSystem/assert_contract.h"
22 #include "SheafSystem/base_space_member.h"
23 #include "SheafSystem/eval_iterator.h"
24 #include "SheafSystem/namespace_poset.h"
25 #include "SheafSystem/sec_vd_space.h"
26 
27 #include "vtkPolyData.h"
28 #include "vtkPolyDataWriter.h"
29 #include "vtkDoubleArray.h"
30 #include "vtkFieldData.h"
31 #include "vtkIntArray.h"
32 
33 #include "vtkPoints.h"
34 #include "vtkCellArray.h"
35 #include "vtkPointData.h"
36 
37 //#unfine DIAGNOSTIC_OUTPUT
38 // #define DIAGNOSTIC_OUTPUT
39 
40 // Workaround for MS Visual C++
41 using namespace tool;
42 using namespace std;
43 
44 // ============================================================================
45 // ANY FACET
46 // ============================================================================
47 
48 
50 bool
52 is_ancestor_of(const any* other) const
53 {
54 
55  // Preconditions:
56 
57  require(other != 0);
58 
59  // Body:
60 
61  // True if other conforms to this
62 
63  bool result = dynamic_cast<const vtk_poly_data_builder*>(other) != 0;
64 
65  // Postconditions:
66 
67  return result;
68 }
69 
70 
71 
75 clone() const
76 {
77  vtk_poly_data_builder* result;
78 
79  // Preconditions:
80 
81  // Body:
82 
83  result = new vtk_poly_data_builder();
84 
85  // Postconditions:
86 
87  ensure(result != 0);
88  ensure(is_same_type(result));
89 
90  // Exit:
91 
92  return result;
93 }
94 
95 
100 {
101 
102  // Preconditions:
103 
104 
105  // Body:
106 
107  not_implemented();
108 
109  // Postconditions:
110 
111  ensure(invariant());
112 
113  // Exit
114 
115  return *this;
116 }
117 
119 bool
121 invariant() const
122 {
123  bool result = true;
124 
125  if(invariant_check())
126  {
127  // Prevent recursive calls to invariant
128 
129  disable_invariant_check();
130 
131  // Must satisfy base class invariant
132 
133  invariance(any::invariant());
134 
135  // Invariances for this class:
136 
140 
141  // Finished, turn invariant checking back on.
142 
143  enable_invariant_check();
144  }
145 
146  // Exit
147 
148  return result;
149 }
150 
151 
152 
153 // ============================================================================
154 // VTK_DATA_SET_BUILDER FACET
155 // ============================================================================
156 
158 tool::vtk_poly_data_builder::
159 vtk_poly_data_builder(const vtk_poly_data_builder& xother)
160 {
161 
162  // Preconditions:
163 
164 
165  // Body:
166 
167  not_implemented();
168 
169  // Postconditions:
170 
171  ensure(invariant());
172 
173  // Exit:
174 
175  return;
176 }
177 
178 
182 {
183 
184  // Preconditions:
185 
186 
187  // Body:
188 
189  // Nothing to do.
190 
191  // Postconditions:
192 
193  // Exit:
194 
195  return;
196 }
197 
199 tool::vtk_poly_data_builder::
200 vtk_poly_data_builder(namespace_poset& xns)
201 {
202  // Preconditions:
203 
204  // Body:
205 
206  _name_space = &xns;
207 
208  // Initialize the mapping from sheaf cell types to vtk cell types.
209 
210  init_cell_type_map();
211 
212  // Postconditions:
213 
214  ensure(invariant());
215 
216  // Exit:
217 
218  return;
219 }
220 
221 
222 
224 void
226 build_file(const sec_vd& xcoords, const sec_vd& xproperty,
227  const std::string& xvtk_file_name, bool xis_ascii)
228 {
229  // Preconditions:
230 
231  require(xcoords.state_is_read_accessible());
233  require(xcoords.schema().df() <= 3);
234  require(xproperty.state_is_read_accessible());
235  require(xproperty.schema().base_space().is_same_state(&xcoords.schema().base_space()));
236  require(xproperty.schema().evaluation().is_same_state(&xcoords.schema().evaluation()));
237  require(!xvtk_file_name.empty());
238 
239  // Body:
240 
241 
242  // Create a vtk data object.
243 
244  vtkPolyData* lug = build(xcoords, xproperty);
245 
246  // Create a vtk data object writer and set it to write
247  // either ascii or binary.
248 
249  vtkPolyDataWriter* writer = vtkPolyDataWriter::New();
250  writer->SetInputData(lug);
251  writer->SetFileName(xvtk_file_name.c_str());
252 
253  if(xis_ascii)
254  writer->SetFileTypeToASCII();
255  else
256  writer->SetFileTypeToBinary();
257 
258  // Actually write the file.
259 
260  writer->Write();
261 
262  // Cleanup.
263 
264  writer->Delete();
265  lug->Delete();
266 
267 
268  // Postconditions:
269 
270 
271  // Exit:
272 
273  return;
274 
275 }
276 
278 void
280 build_file(const sec_vd& xcoords,
281  const std::string& xvtk_file_name, bool xis_ascii)
282 {
283  // Preconditions:
284 
285  require(xcoords.state_is_read_accessible());
287  require(xcoords.schema().df() <= 3);
288  require(!xvtk_file_name.empty());
289 
290  // Body:
291 
292 
293  // Create a vtk data object.
294 
295  vtkPolyData* lug = build(xcoords);
296 
297  // Create a vtk data object writer and set it to write
298  // either ascii or binary.
299 
300  vtkPolyDataWriter* writer = vtkPolyDataWriter::New();
301  writer->SetInputData(lug);
302  writer->SetFileName(xvtk_file_name.c_str());
303 
304  if(xis_ascii)
305  writer->SetFileTypeToASCII();
306  else
307  writer->SetFileTypeToBinary();
308 
309  // Actually write the file.
310 
311  writer->Write();
312 
313  // Cleanup.
314 
315  writer->Delete();
316  lug->Delete();
317 
318 
319  // Postconditions:
320 
321 
322  // Exit:
323 
324  return;
325 }
326 
327 
329 vtkPolyData*
331 build(const sec_vd& xcoords, const sec_vd& xproperty)
332 {
333  vtkPolyData* result;
334 
335  // Preconditions:
336 
337  require(xcoords.state_is_read_accessible());
339  require(xcoords.schema().df() <= 3);
340  require(xproperty.state_is_read_accessible());
341  require(xproperty.schema().base_space().is_same_state(&xcoords.schema().base_space()));
342  require(xproperty.schema().evaluation().is_same_state(&xcoords.schema().evaluation()));
343 
344  // Body:
345 
346  result = vtkPolyData::New();
347 
348  build_pa(xcoords, xproperty, *result);
349 
350  // Postconditions:
351 
352 
353  // Exit:
354 
355  return result;
356 }
357 
359 vtkPolyData*
361 build(const sec_vd& xcoords)
362 {
363  vtkPolyData* result;
364 
365  // Preconditions:
366 
367  require(xcoords.state_is_read_accessible());
369  require(xcoords.schema().df() <= 3);
370 
371  // Body:
372 
373  result = vtkPolyData::New();
374 
375  build_pa(xcoords, *result);
376 
377  // Postconditions:
378 
379 
380  // Exit:
381 
382  return result;
383 }
384 
386 void
388 build_pa(const sec_vd& xcoords, const sec_vd& xproperty, vtkPolyData& xresult)
389 {
390  // Preconditions:
391 
392  require(xcoords.state_is_read_accessible());
394  require(xcoords.schema().df() <= 3);
395  require(xproperty.state_is_read_accessible());
396  require(xproperty.schema().base_space().is_same_state(&xcoords.schema().base_space()));
397  require(xproperty.schema().evaluation().is_same_state(&xcoords.schema().evaluation()));
398  require(&xresult != 0);
399 
400  // Body:
401 
402  construct_mesh(xcoords, xresult);
403 
404  // Add the property to the vtkDataSet
405 
406  construct_property(xproperty, xresult);
407 
408 #ifdef DIAGNOSTIC_OUTPUT
409 
410  vtkIndent lindent;
411  xresult.PrintSelf(cout, lindent);
412 #endif
413 
414  // Postconditions:
415 
416 
417  // Exit:
418 
419  return;
420 }
421 
423 void
425 build_pa(const sec_vd& xcoords, vtkPolyData& xresult)
426 {
427  // Preconditions:
428 
429  require(xcoords.state_is_read_accessible());
431  require(xcoords.schema().df() <= 3);
432  require(&xresult != 0);
433 
434  // Body:
435 
436  construct_mesh(const_cast<sec_vd&>(xcoords), xresult);
437 
438  // Postconditions:
439 
440 
441  // Exit:
442 
443  return;
444 }
445 
446 // ============================================================================
447 // PRIVATE MEMBER FUNCTIONS
448 // ============================================================================
449 
451 tool::vtk_poly_data_builder::
452 vtk_poly_data_builder()
453 {
454 
455  // Preconditions:
456 
457 
458  // Body:
459 
460  not_implemented();
461 
462  // Postconditions:
463 
464  ensure(invariant());
465 
466  // Exit:
467 
468  return;
469 }
470 
472 void
473 tool::vtk_poly_data_builder::
474 init_cell_type_map()
475 {
476  // Preconditions:
477 
478  require(name_space().state_is_read_accessible());
479 
480  // Body:
481 
482  poset* lprototypes =
483  &name_space().member_poset<poset>(base_space_member::prototypes_poset_name(), false);
484  lprototypes->get_read_access();
485 
486  _cell_type_map.reserve(lprototypes->member_index_ub().pod());
487 
488  _cell_type_map.set_ct(_cell_type_map.ub());
489  _cell_type_map.assign(0);
490 
491  base_space_member lmbr;
492  lmbr.attach_to_state(lprototypes, "segment");
493  _cell_type_map.set_item(lmbr.type_id(), 3);
494 
495  lmbr.attach_to_state(lprototypes, "segment_complex");
496  _cell_type_map.set_item(lmbr.type_id(), 3);
497 
498  // lmbr.attach_to_state(lprototypes, "triangle");
499  // _cell_type_map.set_item(lmbr.type_id(), 5);
500 
501  // lmbr.attach_to_state(lprototypes, "triangle_nodes");
502  // _cell_type_map.set_item(lmbr.type_id(), 5);
503 
504  // lmbr.attach_to_state(lprototypes, "quad");
505  // _cell_type_map.set_item(lmbr.type_id(), 9);
506 
507  // lmbr.attach_to_state(lprototypes, "quad_nodes");
508  // _cell_type_map.set_item(lmbr.type_id(), 9);
509 
510  // lmbr.attach_to_state(lprototypes, "hex");
511  // _cell_type_map.set_item(lmbr.type_id(), 12);
512 
513  // lmbr.attach_to_state(lprototypes, "hex_nodes");
514  // _cell_type_map.set_item(lmbr.type_id(), 12);
515 
516  // lmbr.attach_to_state(lprototypes, "tetra");
517  // _cell_type_map.set_item(lmbr.type_id(), 10);
518 
519  // lmbr.attach_to_state(lprototypes, "tetra_nodes");
520  // _cell_type_map.set_item(lmbr.type_id(), 10);
521 
522  lmbr.detach_from_state();
523  lprototypes->release_access();
524 
525  // Postconditions:
526 
527  // Exit:
528 
529  return;
530 }
531 
532 
534 void
535 tool::vtk_poly_data_builder::
536 get_connectivity(const sec_vd& xcoords)
537 {
538  // Preconditions:
539 
540  require(xcoords.state_is_read_accessible());
542  require(xcoords.schema().df() <= 3);
543 
544  // Body:
545 
546  // Count the number of eval cells and connectivity entries.
547 
548  // Allocate the vtk cell type array.
549 
550  size_type leval_ct = xcoords.schema().evaluation_ct();
551  _vtk_cell_types.reserve(leval_ct);
552  _vtk_cell_types.set_ct(0);
553 
554  // Allocate the vtk cell connectivity array.
555 
556  int num_cells = leval_ct;
557 
558  size_type lconn_ct = count_connectivity_entries(xcoords);
559  size_type lconn_tuple_ct = lconn_ct + leval_ct;
560  _vtk_cell_connectivity.reserve(lconn_tuple_ct);
561  _vtk_cell_connectivity.set_ct(0);
562 
563  // Get the client id space for the discretization subposet.
564 
565  const index_space_handle& ldisc_space =
566  xcoords.schema().discretization().id_space();
567 
568  // Iterate over the evluation subposet, transferring the
569  // connectivity and type data.
570 
571  eval_iterator litr(xcoords.schema());
572 
573  while(!litr.is_done())
574  {
575  // Convert the cell type to vtk and transfer to the vtk array.
576 
577  int lvtk_cell_type = _cell_type_map[litr.type_id()];
578  _vtk_cell_types.push_back(lvtk_cell_type);
579 
580  // We're assuming that the discretiation subposet for the coordinate
581  // field is the vertices, so the "discretization members" is the
582  // "connectivity".
583 
584  block<scoped_index>& ldisc_ids = litr.discretization_members();
585  size_type ldisc_ct = ldisc_ids.ct();
586 
587  _vtk_cell_connectivity.push_back(ldisc_ct);
588 
589  // Iterate over the connectivity (discretization members)
590  // for this evaluation member.
591 
592  for(size_type i=0; i<ldisc_ct; ++i)
593  {
594  scoped_index ldisc_id = ldisc_ids[i];
595 
596  int lclient_id = ldisc_space.pod(ldisc_id);
597 
598  // Save the current member of the connectivity.
599 
600  _vtk_cell_connectivity.push_back(lclient_id);
601  }
602 
603  // Move to the next evaluation member.
604 
605  litr.next();
606  }
607 
608  // Postconditions:
609 
610  // Exit:
611 
612  return;
613 }
614 
617 tool::vtk_poly_data_builder::
618 count_connectivity_entries(const sec_vd& xcoords) const
619 {
620  size_type result = 0;
621 
622  // Preconditions:
623 
624  require(xcoords.state_is_read_accessible());
625 
626  // Body:
627 
628  eval_iterator litr(xcoords.schema());
629  while(!litr.is_done())
630  {
631  result += litr.discretization_members().ct();
632  litr.next();
633  }
634 
635  // Postconditions:
636 
637  ensure(result > 0);
638 
639  // Exit:
640 
641  return result;
642 }
643 
644 
647 tool::vtk_poly_data_builder::
648 name_space() const
649 {
650  return *_name_space;
651 }
652 
654 void
655 tool::vtk_poly_data_builder::
656 construct_mesh(const sec_vd& xcoords, vtkPolyData& xresult)
657 {
658  // Preconditions
659 
660  require(xcoords.df() == 1);
661 
662  // Body:
663 
664  // Allocate the vtk points object for the coordinates field.
665 
666  vtkPoints* vtk_points = vtkPoints::New();
667  int num_points = xcoords.schema().discretization_ct();
668  vtk_points->SetNumberOfPoints(num_points);
669 
670  int num_vtk_points = vtk_points->GetNumberOfPoints();
671 
672  int coord_dof_count = get_dof_count(xcoords);
673 
674  dof_type* coord_dofs = get_dofs(const_cast<sec_vd&>(xcoords));
675 
676  vtkDoubleArray* vtk_coord_dofs = vtkDoubleArray::New();
677  vtk_coord_dofs->SetName(xcoords.name().c_str());
678 
679  int num_comps = xcoords.df();
680 
681  vtk_coord_dofs->SetNumberOfComponents(3); // Must be 3 for vtkPoints (coordinates)
682 
683  dof_type x[3];
684 
685  int num_tuples = coord_dof_count/num_comps;
686  vtk_coord_dofs->SetNumberOfTuples(num_tuples);
687  int index = 0;
688  for(int i=0; i<num_tuples; ++i)
689  {
690  x[0] = coord_dofs[index++];
691  if(num_comps==2)
692  x[1] = coord_dofs[index++];
693  else
694  x[1] = 0.0;
695  x[2] = 0.0;
696  vtk_coord_dofs->SetTuple(i, x);
697  }
698 
699  vtk_points->SetData(vtk_coord_dofs);
700  vtk_points->SetDataTypeToDouble();
701 
702  // Connectivity:
703 
704  get_connectivity(xcoords);
705 
706  vtkCellArray* vtk_cells = vtkCellArray::New();
707  int num_cells = _vtk_cell_types.ct();
708  vtk_cells->Allocate(num_cells);
709 
710  vtkIdTypeArray* vtk_connectivity = vtkIdTypeArray::New();
711  vtk_connectivity->SetNumberOfComponents(1);
712  vtk_connectivity->SetArray(_vtk_cell_connectivity.base(), _vtk_cell_connectivity.ct(), 1);
713 
714  vtk_cells->SetCells(num_cells, vtk_connectivity);
715 
716  xresult.SetPoints(vtk_points);
717  xresult.SetPolys(vtk_cells);
718 
719  vtk_points->Delete();
720  vtk_cells->Delete();
721  vtk_connectivity->Delete();
722  vtk_coord_dofs->Delete();
723 
724  // Postconditions:
725 
726 }
727 
729 void
731 construct_property(const sec_vd& xproperty, vtkPolyData& xresult)
732 {
733  // Preconditions:
734 
735  require(xproperty.df() == 1);
736 
737  // Body:
738 
739  vtkDoubleArray* propertyArray = vtkDoubleArray::New();
740 
741  int dof_count = get_dof_count(xproperty);
742  dof_type* dofs = get_dofs(xproperty);
743 
744  propertyArray->SetName(xproperty.name().c_str());
745 
746  sec_rep_space* lhost = xproperty.host();
747 
748  propertyArray->SetNumberOfComponents(1);
749  propertyArray->SetArray(dofs, dof_count, 1);
750  xresult.GetPointData()->SetScalars(propertyArray);
751 
752  propertyArray->Delete();
753 
754  // Postconditions:
755 
756 }
757 
758 
760 int
761 tool::vtk_poly_data_builder::
762 get_dof_count(const sec_vd& xmbr) const
763 {
764  return xmbr.schema().row_dof_ct();
765 }
766 
768 tool::vtk_poly_data_builder::dof_type*
769 tool::vtk_poly_data_builder::
770 get_dofs(const sec_vd& xmbr) const
771 {
772  const section_dof_map& dof_map = xmbr.dof_map();
773 
774  dof_type* result = reinterpret_cast<dof_type*>(const_cast<section_dof_map&>(dof_map).dof_tuple());
775 
776  return result;
777 }
778 
779 // ============================================================================
780 // NON-MEMBER FUNCTIONS
781 // ============================================================================
782 
virtual bool invariant() const
Class invariant, intended to be redefined in each descendant. See below for template for invariant in...
Definition: any.cc:153
int df() const
The dimension of the restricted fiber.
host_type * host() const
The poset this is a member of.
Definition: sec_vd.cc:1353
size_type ct() const
The number of items currently in use.
const pod_type & pod() const
The "plain old data" storage of this; the value in the external id space.
Definition: scoped_index.h:672
The abstract map from section dof ids to section dof values of heterogeneous type.
bool conforms_to(const schema_poset_member &xother) const
True if the dofs defined by this agree in type and in order with the dofs defined by xother...
The default name space; a poset which contains other posets as members.
bool state_is_read_accessible() const
True if this is attached and if the state is accessible for read or access control is disabled...
An iterator over the members of the evaluation subposet contained in the downset of the base space of...
Definition: eval_iterator.h:66
subposet & evaluation()
The evaluation subposet for section spaces on this schema (mutable version).
vtkPolyData * build(const sec_vd &xcoords, const sec_vd &xproperty)
Builds a vtkPolyData from xcoords and xproperty.
STL namespace.
bool is_same_state(const poset_state_handle *xhost, pod_index_type xhub_id) const
True is this is attached to state with hub id xhub_id in host xhost.
An abstract handle to a space of alternate integer identifiers (aliases) for a subset of a hub set of...
const pod_index_type & type_id() const
The cell type id of this. The id of the prototype of this in the "cell_types" id space of the prototy...
std::string name() const
A name for this.
static const std::string & prototypes_poset_name()
The name of the prototypes poset.
vtk_poly_data_builder & operator=(const vtk_poly_data_builder &xother)
Assignment operator.
A client handle for a member of a base space poset.
Namespace for the tools component of the sheaf system.
Abstract base class with useful features for all objects.
Definition: any.h:39
virtual vtk_poly_data_builder * clone() const
Virtual constructor, makes a new instance of the same type as this.
void build_file(const sec_vd &xcoords, const sec_vd &xproperty, const std::string &xvtk_file_name, bool xis_ascii=true)
Builds a vtk file representation of a vtkPolyData from xcoords and xproperty with file name xvtk_file...
A client handle for a mutable partially ordered set.
Definition: poset.h:40
An index within the external ("client") scope of a given id space.
Definition: scoped_index.h:116
unsigned long size_type
An unsigned integral type used to represent sizes and capacities.
Definition: sheaf.h:52
virtual ~vtk_poly_data_builder()
Destructor.
int discretization_ct() const
The number of members in the intersection of the discretization subposet and the down set of the base...
static int row_dof_ct(const namespace_poset &xns, const poset_path &xpath, bool xauto_access=true)
The number of row dofs defined by the schema specified by xns and xpath. Synonym for dof_ct(xns...
subposet & discretization()
The discretization subposet for section spaces on this schema (mutable version).
virtual void release_access(bool xall=false) const
Release access. If xall is true, release all levels of access. Otherwise, release one level of access...
Creates a vtkPolyData from sheaf field objects.
virtual pod_type pod(pod_type xid) const =0
The pod index in this space equivalent to xid in the hub id space.
A section of a fiber bundle with a d-dimensional vector space fiber.
Definition: sec_vd.h:54
void construct_property(const sec_vd &xproperty, vtkPolyData &xresult)
Construct the VTK "mesh" (vtkPolyData) object.
const scattered_insertion_index_space_handle & id_space() const
The id space for the members of with this (const version).
Definition: subposet.cc:508
static const poset_path & standard_schema_path()
The path of the schema required by this class.
virtual void detach_from_state()
Detach this handle from its state, if any.
virtual bool is_ancestor_of(const any *other) const
Conformance test; true if other conforms to this.
total_poset_member & base_space()
The base space component of this (mutable version).
virtual section_space_schema_member & schema()
The restricted schema for this (mutable version).
virtual scoped_index member_index_ub() const
The upper bound on the member_index;.
int evaluation_ct() const
The number of members in the intersection of the evaluation subposet and the down set of the base spa...
virtual bool invariant() const
Class invariant.
int df() const
The dimension of the fiber space component.
void attach_to_state(const namespace_poset *xns, const poset_path &xpath, bool xauto_access=true)
Attach to the state specified by path xpath in the namespace xns.
virtual void get_read_access() const
Get read access to the state associated with this.
block< scoped_index > & discretization_members()
The discretization members in the downset of the current evaluation member (mutable version)...
virtual schema_poset_member & schema()
The schema for this member (mutable version).
virtual section_dof_map & dof_map(bool xrequire_write_access=false)
The map from client_ids to dof values for this poset member (mutable version)
void build_pa(const sec_vd &xcoords, const sec_vd &xproperty, vtkPolyData &xresult)
Builds a vtkPolyData from xcoords and xproperty (pre-allocated version).
A handle for a poset whose members are numerical representations of sections of a fiber bundle...
Definition: sec_rep_space.h:61