root/cgm/trunk/geom/virtual/CAPartitionVG.cpp

Revision 1040, 14.4 KB (checked in by tautges, 2 years ago)

Version 10.2 of cgm.

  • Property svn:executable set to *
Line 
1// CAPartitionVG class
2
3#include <vector>
4#include <utility>
5#include <algorithm>
6
7#include "CAPartitionVG.hpp"
8#include "TDUniqueId.hpp"
9#include "CastTo.hpp"
10#include "RefFace.hpp"
11#include "RefEdge.hpp"
12#include "RefVertex.hpp"
13#include "PartitionEntity.hpp"
14#include "PartitionTool.hpp"
15#include "BasicTopologyEntity.hpp"
16#include "PartitionCurve.hpp"
17#include "PartitionSurface.hpp"
18#include "CAVirtualVG.hpp"
19#include "MergeTool.hpp"
20
21struct my_sort : public std::binary_function< std::pair<double, int>, std::pair<double, int>, bool> {
22  bool operator() (std::pair<double, int> const& x, std::pair<double, int> const & y ) { return x.first < y.first; }
23};
24
25CubitAttrib* CAPartitionVG_creator(RefEntity* entity, CubitSimpleAttrib *p_csa)
26{
27  CAPartitionVG *new_attrib = NULL;
28  if (NULL == p_csa)
29  {
30    new_attrib = new CAPartitionVG(entity);
31  }
32  else
33  {
34    new_attrib = new CAPartitionVG(entity, p_csa);
35  }
36
37  return new_attrib;
38}
39
40CAPartitionVG::CAPartitionVG(RefEntity *owner) 
41        : CubitAttrib(owner)
42{
43  numPC = 0;
44  numPS = 0;
45}
46
47CAPartitionVG::CAPartitionVG(RefEntity *owner, CubitSimpleAttrib *simple_attrib) 
48        : CubitAttrib(owner)
49{
50    // generate a simple attribute containing the data in this CA
51  DLIList<CubitString*> *cs_list = simple_attrib->string_data_list();
52  DLIList<double*> *d_list = simple_attrib->double_data_list();
53  DLIList<int*> *i_list = simple_attrib->int_data_list();
54
55  cs_list->reset();
56  d_list->reset();
57  i_list->reset();
58 
59    // (no string)
60
61    // now the integers
62    // numVP, numVC
63  numPC = *(i_list->get_and_step());
64  numPS = *(i_list->get_and_step());
65
66    // numBdyCurves
67  int temp, i, sum = 0;
68  for (i = numPS; i > 0; i--) {
69    temp = *(i_list->get_and_step());
70    numBdyCurves.append(temp);
71    sum += temp;
72  }
73
74    // vgUIDs: 3 for each PC, numPS+sum for PS
75  for (i = 3*numPC+sum+numPS; i > 0; i--)
76    vgUIDs.append(*(i_list->get_and_step()));
77
78
79   // If the CubitSimpleAttrib already exists,
80   // then this attribute is already written
81  has_written(CUBIT_TRUE);
82}
83
84CubitStatus CAPartitionVG::update()
85{
86/*
87    // this attribute behaves in a peculiar way: it detects whether the owner
88    // is itself a partition entity, and if so, adds data about this partition
89    // entity to the underlying entity
90
91  if (hasUpdated) return CUBIT_SUCCESS;
92 
93  assert(attrib_owner() != 0);
94
95  TopologyEntity *topo_entity = CAST_TO(attrib_owner(), TopologyEntity);
96  assert(topo_entity != 0);
97  DLIList<TopologyBridge*> bridge_list;
98  topo_entity->bridge_manager()->get_bridge_list( bridge_list );
99  for( int i = bridge_list.size(); i--; )
100  {
101    TopologyBridge *topo_bridge = bridge_list.get_and_step();
102    PartitionEntity *partition_entity = CAST_TO(topo_bridge, PartitionEntity);
103
104  if (partition_entity == NULL) {
105      // this entity isn't a partition entity - if this entity doesn't have any virtual
106      // entities registered, set delete flag, then exit
107    if (numPC == 0 && numPS == 0)
108      delete_attrib(CUBIT_TRUE);
109    else {
110      PRINT_INFO("Keeping CA_PARTITION_VG for %s %d\n",
111                 attrib_owner()->class_name(), attrib_owner()->id());
112      hasUpdated = CUBIT_TRUE;
113    }
114   
115    continue;
116  }
117 
118    // ok, we have a partition entity; first get the underlying entity, and a CAPVG
119    // for that entity
120  BasicTopologyEntity* bte_ptr = partition_entity->get_underlying_BTE_ptr();
121  if (!bte_ptr) {
122    PRINT_ERROR("Couldn't find bound_to\n");
123    return CUBIT_FAILURE;
124  }
125 
126  CAPartitionVG *other_CAPVG = (CAPartitionVG *) bte_ptr->get_cubit_attrib(CA_PARTITION_VG);
127
128    // if that other CAPVG's written flag is set, it's an old one from a
129    // previous write and needs to be reset
130  if (other_CAPVG->has_written() == CUBIT_TRUE) {
131    other_CAPVG->reset();
132    other_CAPVG->has_written(CUBIT_FALSE);
133  }
134
135    // now put virtual geometry-specific data on the attribute
136  PartitionCurve *partition_curve = CAST_TO(partition_entity, PartitionCurve);
137  PartitionSurface *partition_surface = CAST_TO(partition_entity, PartitionSurface);
138 
139  if (partition_curve != NULL) {
140    other_CAPVG->add_pcurve(partition_curve);
141    other_CAPVG->delete_attrib(CUBIT_FALSE);
142  }
143
144  else if (partition_surface != NULL) {
145    other_CAPVG->add_psurface(partition_surface);
146    other_CAPVG->delete_attrib(CUBIT_FALSE);
147  }
148
149  else {
150    PRINT_ERROR("Shouldn't get here in CAPartitionVG::update.\n");
151    return CUBIT_FAILURE;
152  }
153  }
154
155  hasUpdated = CUBIT_TRUE;
156  if (numPC == 0 && numPS == 0) delete_attrib(CUBIT_TRUE);
157 
158  return CUBIT_SUCCESS;
159*/ 
160  delete_attrib(CUBIT_TRUE);
161  return CUBIT_SUCCESS;
162}
163
164
165CubitStatus CAPartitionVG::reset()
166{
167  numPC = 0;
168  numPS = 0;
169 
170  vgUIDs.clean_out();
171  numBdyCurves.clean_out();
172 
173  return CUBIT_SUCCESS;
174}
175
176CubitSimpleAttrib *CAPartitionVG::cubit_simple_attrib()
177{
178    // generate a simple attribute containing the data in this CA
179  DLIList<CubitString*> cs_list;
180  DLIList<double> d_list;
181  DLIList<int> i_list;
182
183    // first the string
184  cs_list.append(new CubitString(att_internal_name()));
185
186    // now the integers
187    // numVP, numVC
188  i_list.append(numPC);
189  i_list.append(numPS);
190
191    // numBdyCurves
192  int i;
193  for (i = numBdyCurves.size(); i > 0; i--)
194    i_list.append(numBdyCurves.get_and_step());
195
196    // vgUIDs
197  vgUIDs.reset();
198  for (i = vgUIDs.size(); i > 0; i--)
199    i_list.append(vgUIDs.get_and_step());
200
201  CubitSimpleAttrib* csattrib_ptr = new CubitSimpleAttrib(&cs_list,
202                                                          &d_list,
203                                                          &i_list);
204
205  for( i=cs_list.size(); i--;) delete cs_list.get_and_step();
206
207  return csattrib_ptr;
208}
209
210CubitStatus CAPartitionVG::actuate()
211{
212    // actuate this CA
213
214    // actuate partition VG attributes on next-lower order entities
215  RefEntity *owner = CAST_TO(attrib_owner(), RefEntity);
216  if (owner->dimension() > 1) {
217    DLIList<RefEntity*> lower_entities;
218    owner->get_child_ref_entities(lower_entities);
219
220      // don't check return values here - there may be other CA's hanging
221      // around unactuated, but we may still be able to actuate later
222    CubitAttribUser::actuate_cubit_attrib(lower_entities, CA_PARTITION_VG);
223    CubitAttribUser::actuate_cubit_attrib(lower_entities, CA_VIRTUAL_VG);
224  }
225
226  //actuate it
227
228    // if this is an edge, now partition it
229  RefEdge *owner_edge = CAST_TO(owner, RefEdge);
230  RefFace *owner_face = CAST_TO(owner, RefFace);
231
232  //have to get some of the data from CAVirtualVG in order to partition
233  //get CA_VIRTUAL_VG attrib associated with this entity
234  DLIList<CubitAttrib*> vg_attribs;
235  attrib_owner()->find_cubit_attrib_type( CA_VIRTUAL_VG, vg_attribs );
236  CAVirtualVG *ca_vg_ptr = NULL;
237  if( vg_attribs.size() != 0 )
238    ca_vg_ptr = CAST_TO( vg_attribs.get(), CAVirtualVG );
239
240  DLIList<RefFace*> new_faces;
241  DLIList<RefEdge*> new_edges;
242
243  int i,j,k;
244  if (owner_edge) //if an edge has been partitioned
245  {
246    DLIList<RefVertex*> new_vertices;
247    DLIList<RefEdge*> new_edges;
248    DLIList<CubitVector*> split_points;
249     
250    if( !ca_vg_ptr ) //if NO virtual geometry has been used to partiton this curve
251    {
252      //get vertices of curve
253      DLIList<RefEntity*> lower_entities;
254      owner->get_child_ref_entities(lower_entities);
255
256      //get the points that are not owned by a vertex 
257      vgUIDs.reset();
258      DLIList<RefVertex*> vertices;
259      for(i=vgUIDs.size()/3; i--;)
260      {
261        ToolDataUser *tdu = TDUniqueId::find_td_unique_id(vgUIDs.get_and_step());
262        RefVertex *s_vert = CAST_TO( tdu, RefVertex ); 
263        tdu = TDUniqueId::find_td_unique_id(vgUIDs.get_and_step());
264        RefVertex *e_vert = CAST_TO( tdu, RefVertex ); 
265     
266        //get vertices owned by this curve
267        if( !lower_entities.move_to( s_vert ) )
268          vertices.append_unique( s_vert );
269        if( !lower_entities.move_to( e_vert ) )
270          vertices.append_unique( e_vert );
271
272        vgUIDs.step();
273      }
274      //convert vertices to vectors to split curve
275      for(i=vertices.size(); i--;)
276      {
277        RefVertex *cur_vertex = vertices.get_and_step();
278        split_points.append( new CubitVector( cur_vertex->coordinates() ) );
279      }
280
281      //partition the curve with these split points
282      split_points.reset(); 
283      PartitionTool::instance()->partition( owner_edge, split_points,
284                                            new_vertices, new_edges );
285      //may need to merge some vertices
286      vertices += new_vertices;
287      MergeTool::instance()->merge_refvertices( vertices );
288
289    }
290    else //virtual geometry HAS been used to partiton this curve
291    {
292      split_points = ca_vg_ptr->posVector;
293      DLIList<int>vertex_unique_ids = ca_vg_ptr->vgUIDs;
294      std::vector< std::pair<double, int> > list_of_pairs;
295
296      //before partitioning edge, reorder split points, from lowest u to
297      //highest u; we use a pair so that the corresponding uids are reordered as well
298      for( i=split_points.size(); i--;)
299      {
300        CubitVector *split_point = split_points.get_and_step();
301        double u_param = owner_edge->u_from_position( *split_point );
302        int uuid = vertex_unique_ids.get_and_step();
303        std::pair<double, int> my_pair;
304        my_pair.first = u_param;
305        my_pair.second = uuid;
306        list_of_pairs.push_back( my_pair );
307      }
308     
309      std::sort(list_of_pairs.begin(), list_of_pairs.end(), my_sort() ); 
310
311      //partition the curve with these split points
312      split_points.reset(); 
313      PartitionTool::instance()->partition( owner_edge, split_points,
314                                            new_vertices, new_edges );
315         
316      assert( list_of_pairs.size() == (unsigned int)new_vertices.size() );
317      //associate the vertex uuids with the new vertices
318      new_vertices.reset();
319      vertex_unique_ids.reset();
320      std::vector< std::pair<double, int> >::iterator iter = list_of_pairs.begin();
321      for( i=new_vertices.size(); i--; )
322      {
323        new TDUniqueId( new_vertices.get_and_step(), (*iter).second );
324        iter++;
325      }
326    }
327
328    //associate the curve uuids with the new curve
329    new_edges.reset();
330    RefEdge* ref_edge;
331    vgUIDs.reset();
332    for( i=new_edges.size(); i--; )
333    {
334      ref_edge = new_edges.get_and_step();
335      //get uuids of start and end vertices on curve
336      RefVertex *start_vertex = ref_edge->start_vertex();
337      RefVertex *end_vertex = ref_edge->end_vertex();
338
339      int s_vert_uuid = TDUniqueId::get_unique_id( start_vertex );
340      int e_vert_uuid = TDUniqueId::get_unique_id( end_vertex );
341     
342      for( j=vgUIDs.size(); j--;)
343      { 
344        int s_uuid = vgUIDs.get_and_step();
345        int e_uuid = vgUIDs.get_and_step();
346        if( (s_vert_uuid == s_uuid && e_vert_uuid == e_uuid ) ||
347            (e_vert_uuid == s_uuid && s_vert_uuid == e_uuid ) )
348        {
349         new TDUniqueId( ref_edge, vgUIDs.get_and_step() );
350         break;
351        }
352        else
353          vgUIDs.step();
354      }
355    }
356  }
357  else if (owner_face)  //partition a surface
358  {
359    DLIList<RefFace*> input_faces;
360    input_faces.append( owner_face );
361    DLIList<CubitVector*> segments;
362
363    //for each virtual curve used to partition surface
364    ca_vg_ptr->numVCPoints.reset();
365    ca_vg_ptr->posVector.reset();
366    ca_vg_ptr->vgUIDs.step( ca_vg_ptr->numVV );
367    for( i=ca_vg_ptr->numVC; i--;)
368    {
369      //get coordinates of start/end vertices of virtual curve
370      ToolDataUser *tdu = TDUniqueId::find_td_unique_id(ca_vg_ptr->vgUIDs.get_and_step());
371      RefVertex *s_vert = CAST_TO( tdu, RefVertex ); 
372      tdu = TDUniqueId::find_td_unique_id(ca_vg_ptr->vgUIDs.get_and_step());
373      RefVertex *e_vert = CAST_TO( tdu, RefVertex ); 
374      DLIList<RefVertex*> vertices;
375
376      CubitVector *vec1, *vec2;
377      if( s_vert)
378      {
379        vec1 = new CubitVector(s_vert->coordinates());
380        vertices.append( s_vert );
381      }
382
383      else
384        vec1 = new CubitVector( *(ca_vg_ptr->posVector.get() ));
385     
386      segments.append( vec1 );
387
388      if( e_vert)
389      {
390        vec2 = new CubitVector(e_vert->coordinates());
391        vertices.append( e_vert );
392      }
393      else
394        vec2 = new CubitVector( *(ca_vg_ptr->posVector.get() ));
395
396      //append any intermediate segments
397      for( j=ca_vg_ptr->numVCPoints.get_and_step(); j--; ) 
398        segments.append( ca_vg_ptr->posVector.get_and_step() );
399
400      segments.append( vec2 );
401      //partition the surf
402      new_edges.clean_out();
403      new_faces.clean_out();
404      PartitionTool::instance()->insert_edge( input_faces, segments,
405                                              new_faces, new_edges);
406
407      //may need to merge some vertices
408      DLIList<RefVertex*> verts_to_merge;
409      for( j=new_edges.size(); j--;)
410      {
411        verts_to_merge.append( new_edges.get()->start_vertex() );
412        verts_to_merge.append( new_edges.get()->end_vertex() );
413      }
414      verts_to_merge += vertices;
415      verts_to_merge.uniquify_unordered();
416
417      MergeTool::instance()->merge_refvertices( verts_to_merge  );
418
419      //give new edge uuids
420      new_edges.reset();
421      for( j=new_edges.size(); j--;)
422        new TDUniqueId( new_edges.get_and_step(), ca_vg_ptr->vgUIDs.get_and_step() );
423     
424      delete vec1;
425      delete vec2;
426      segments.clean_out();
427   
428   
429    //associate the face uuids with the new faces
430    new_faces.reset();
431    RefFace* ref_face;
432    vgUIDs.reset();
433    for( j=new_faces.size(); j--; )
434    {
435      ref_face = new_faces.get_and_step();
436
437      //get uuids of each edge in surface   
438      DLIList<RefEdge*> edges;
439      ref_face->ref_edges( edges );
440      DLIList<int> edge_uuids;
441
442      edges.reset();
443      for( k=edges.size(); k--;)
444        edge_uuids.append( TDUniqueId::get_unique_id( edges.get_and_step() ));
445
446      //look at all the groups of boundary edges of each surface
447      vgUIDs.reset();
448      for( k=numBdyCurves.size(); k--;)
449      {
450        int kk;
451        DLIList<int> bdy_curve_uuids;
452        int num_bdy_curves = numBdyCurves.get_and_step();
453        if( edge_uuids.size() != num_bdy_curves )
454          continue;
455        for( kk=num_bdy_curves; kk--;)
456          bdy_curve_uuids.append( vgUIDs.get_and_step());
457             
458        CubitBoolean match = CUBIT_TRUE;
459        kk=num_bdy_curves;
460        while( kk && match )
461        {
462          kk--;
463          if( !bdy_curve_uuids.move_to( edge_uuids.get_and_step() ) )
464          {
465            match = CUBIT_FALSE; 
466            break;
467          }
468        }
469        if( match )
470        {
471          new TDUniqueId( ref_face, vgUIDs.get() );
472          break;
473        }
474        vgUIDs.step();
475      }
476    }
477
478    input_faces.clean_out();
479    input_faces += new_faces;
480
481    }
482  }
483 
484  hasActuated = CUBIT_TRUE;
485 
486   // otherwise, we're done
487  return CUBIT_SUCCESS;
488}
489
490
Note: See TracBrowser for help on using the browser.