Salome HOME
Merge from V6_main 01/04/2013
[modules/hexablock.git] / src / HEXABLOCK / HexDocument_asso.cxx
1
2 // C++ : Associations dans le document
3
4 // Copyright (C) 2009-2013  CEA/DEN, EDF R&D
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include "HexDocument.hxx"
23 #include "HexEdge.hxx"
24 #include "HexQuad.hxx"
25 #include "HexDiagnostics.hxx"
26 #include "HexNewShape.hxx"
27 #include "HexEdgeShape.hxx"
28
29 BEGIN_NAMESPACE_HEXA
30
31 static bool db = on_debug ();  // == getenv ("HEXA_DB") > 0
32
33
34 int vertexInLine (Vertex* vfirst, Edges& mline, vector<int> &tsens);
35 // ====================================================== vertexInLine
36 int vertexInLine (Vertex* vfirst, Edges& mline, vector<int> &tsens)
37 {
38    int nbseg = mline.size ();
39
40    for (int ned = 0 ; ned<nbseg ; ned++)
41        {
42        if (tsens [ned] == V_TWO)
43           for (int ns=V_AMONT; ns<=V_AVAL ; ns++)
44               {
45               if (mline[ned]->getVertex (ns) == vfirst)
46                  {
47                  tsens [ned] = ns;
48                  return ned;
49                  }
50               }
51        }
52
53    return NOTHING;
54 }
55 // ====================================================== clearAssociation
56 void Document::clearAssociation ()
57 {
58    clearAssoVertices ();
59    clearAssoEdges ();
60    clearAssoQuads ();
61 }
62 // ====================================================== clearAssociation (t)
63 int Document::clearAssociation (EnumElt type)
64 {
65    switch (type)
66       {
67       case EL_VERTEX  :
68            clearAssoVertices ();
69            break;
70       case EL_EDGE  :
71            clearAssoEdges ();
72            break;
73       case EL_QUAD  :
74            clearAssoQuads ();
75            break;
76       default : return HERR;
77       }
78
79    return HOK;
80 }
81 // ====================================================== clearAssoVertices
82 void Document::clearAssoVertices ()
83 {
84    for (EltBase* elt = doc_first_elt[EL_VERTEX]->next (); elt!=NULL;
85                  elt = elt->next())
86        {
87        Vertex* elem = static_cast <Vertex*> (elt);
88        if (elem->isValid ())
89            elem->clearAssociation ();
90        }
91 }
92 // ====================================================== clearAssoEdges
93 void Document::clearAssoEdges ()
94 {
95    for (EltBase* elt = doc_first_elt[EL_EDGE]->next (); elt!=NULL;
96                  elt = elt->next())
97        {
98        Edge* elem = static_cast <Edge*> (elt);
99        if (elem->isValid ())
100            elem->clearAssociation ();
101        }
102 }
103 // ====================================================== clearAssoQuads
104 void Document::clearAssoQuads ()
105 {
106    for (EltBase* elt = doc_first_elt[EL_VERTEX]->next (); elt!=NULL;
107                  elt = elt->next())
108        {
109        Quad* elem = static_cast <Quad*> (elt);
110        if (elem->isValid ())
111            elem->clearAssociation ();
112        }
113 }
114 // ====================================================== addShape (1)
115 NewShape* Document::addShape (TopoDS_Shape& topo, cpchar name)
116 {
117    NewShape* shape = new NewShape (this);
118    doc_tab_shape.push_back (shape);
119
120    shape->setName  (name);
121    shape->setShape (topo);
122    return shape;
123 }
124 // ====================================================== addShape (2)
125 NewShape* Document::addShape (cpchar name, EnumShape type)
126 {
127    NewShape* shape = new NewShape (this, type);
128    doc_tab_shape.push_back (shape);
129
130    shape->setName  (name);
131    return shape;
132 }
133 // ====================================================== addCloud
134 void Document::addCloud ()
135 {
136    doc_cloud = new NewShape (this, SH_CLOUD);
137    doc_cloud->setName  ("cloud");
138
139    doc_tab_shape.push_back (doc_cloud);
140 }
141 // ====================================================== getShape
142 NewShape* Document::getShape (int nro)
143 {
144    int nbre = doc_tab_shape.size ();
145    if (nro < 0 || nro >= nbre)
146       return NULL;
147
148    return doc_tab_shape [nro];
149 }
150 // ====================================================== findShape
151 NewShape* Document::findShape (rcstring nom)
152 {
153    int nbre = doc_tab_shape.size ();
154    for (int nro=0 ; nro<nbre ; ++nro)
155        if (nom == doc_tab_shape [nro]->getName())
156           return  doc_tab_shape [nro];
157 }
158 // ====================================================== find_line
159 EdgeShape* find_line (EdgeShapes& gline, double* point, int& sens)
160 {
161    int nbseg = gline.size ();
162
163    for (int ned = 0 ; ned<nbseg ; ned++)
164        {
165        EdgeShape* edge = gline [ned];
166        if (edge!=NULL)
167           {
168           sens = edge->onExtremity (point);
169           if (sens >=0)
170              {
171              gline [ned] = NULL;
172              return edge;
173              }
174           }
175        }
176    return NULL;
177 }
178 // ====================================================== find_edge
179 Edge* find_edge (Edges& mline, Vertex* vfirst, int& sens)
180 {
181    int nbseg = mline.size ();
182
183    for (int ned = 0 ; ned<nbseg ; ned++)
184        {
185        Edge* edge = mline [ned];
186        if (edge!=NULL)
187           {
188           sens = edge->index (vfirst);
189           if (sens >=0)
190              {
191              mline [ned] = NULL;
192              return edge;
193              }
194           }
195        }
196    return NULL;
197 }
198 // ====================================================== associateOpenedLine
199 int Document::associateOpenedLine (Edges&  mline, NewShapes& gline,
200                                    IntVector& tabid,
201                                    double pstart, double pend)
202 {
203    cout << "_________________________________ Asso Open Line"
204         << " ed=" << mline.size()
205         << " sh=" << tabid.size()
206         << endl;
207    int ier = associateLine (NULL, mline, gline, tabid, pstart, pend, false);
208    return ier;
209 }
210 // ====================================================== associateClosedLine
211 int Document::associateClosedLine (Vertex* vfirst,   Edges&  mline,
212                                    NewShapes& gline, IntVector& tabid,
213                                    double pstart, bool inv)
214 {
215    if (vfirst == NULL)
216       {
217       putError (W_ASSO_LINE3);
218       return HERR;
219       }
220
221    cout << "_________________________________ Asso Closed Line"
222         << " first=" << vfirst->getName()
223         << " ed=" << mline.size()
224         << " sh=" << tabid.size()
225         << " inv=" << inv
226         << endl;
227    int ier = associateLine (vfirst, mline, gline, tabid, pstart, 1.0, inv);
228    PutData (ier);
229    return ier;
230 }
231 // ====================================================== associateLine
232 int Document::associateLine (Vertex* vfirst, Edges& mline,
233                              NewShapes& tshapes, IntVector& subid,
234                              double pstart, double pend, bool inv)
235 {
236    EdgeShapes glines;
237    Edges      tedges;
238    IntVector  gsens, tsens;
239    double     lgtotale;
240
241    bool closed = vfirst!=NULL;
242    int ier = sortShapes (tshapes, subid, closed, inv, pstart, pend,
243                          glines,  gsens, lgtotale);
244    if (ier != HOK)
245        return ier;
246
247    ier = sortEdges (vfirst, mline, tedges, tsens);
248    if (ier != HOK)
249        return ier;
250
251    int nbedges  = tedges.size();
252    int nblines  = glines.size();
253
254    EdgeShape* gstart  = glines [0];
255    EdgeShape* gend    = glines [nblines-1];
256    bool       boucle  = closed && nblines==1;
257
258    double abstart = inv ? (1-pstart) : pstart;
259    if (NOT closed)
260       {
261       bool   rev     = gsens  [nblines-1]!=0;
262       double abend   = rev ?  pend      : (1-pend);
263       lgtotale = lgtotale - abstart * gstart->getLength()
264                           - abend   * gend  ->getLength();
265       }
266                                               // 1er point
267    Real3  point;
268    gstart->getPoint (pstart, point);
269    int vsid     = doc_cloud->addPoint  (point);
270    Vertex* node = tedges[0]->getVertex (tsens[0]);
271    node->setAssociation (doc_cloud, vsid);
272
273    double lgedge = lgtotale/nbedges;
274    double smin   = 0;
275    double smax   = gstart->getLength()*(1-abstart);
276    double emax   = lgedge;
277    double pdeb   = pstart;
278    double ablast = 0;
279    double tol    = 1e-2;
280
281    int nsh   = 0;
282    int ned   = 0;
283    while (ned < nbedges && nsh < nblines)
284        {
285        EdgeShape* shape = glines [nsh];
286        Edge*      edge  = tedges [ned];
287        bool       grev  = gsens  [nsh]==1;
288        bool    av_shape = smax < emax + tol;
289        bool    av_edge  = emax < smax + tol;
290        bool    vassoc   = av_edge && NOT (closed && ned == nbedges-1);
291        double  pfin     = 1;
292        double  lgshape  = shape->getLength ();
293
294        double abscisse = std::min (emax, smax);
295        double decal    = (abscisse-ablast) / lgshape;
296        if (grev)
297           {
298           pfin = pdeb - decal;
299           if (pfin < 0.0) pfin = 0;
300           }
301        else
302           {
303           pfin = pdeb + decal;
304           if (pfin > 1.0) pfin = 1;
305           }
306
307        edge->addAssociation (shape, pdeb, pfin);
308
309        if (vassoc)
310           {
311           shape->getPoint (pfin, point);
312           vsid  = doc_cloud->addPoint  (point);
313           node  = edge  ->getVertex (1-tsens[ned]);
314
315           node->setAssociation (doc_cloud, vsid);
316           }
317        ablast = abscisse;
318        pdeb   = pfin;
319                        // On incremente les edges
320        if (av_edge)
321           {
322           ned ++;
323           emax += lgedge;
324           }
325                        // On incremente les shapes
326        if (av_shape)
327           {
328           pdeb = 0;
329           if (boucle)
330              {
331              smin = smax;
332              smax = shape->getLength ();
333              }
334           else
335              {
336              nsh ++;
337              if (nsh<nblines)
338                 {
339                  smin = smax;
340                  smax += glines[nsh]->getLength();
341                  }
342              }
343           }
344        }
345
346    return HOK;
347 }
348 // ====================================================== sortShapes
349 int Document::sortShapes (NewShapes&  tshapes, IntVector& subid, bool closed,
350                       bool inv, double pstart, double pend,
351                       EdgeShapes& glines,  IntVector& gsens, double& lgtotale)
352 {
353    char cnum [8];
354    int nblines = subid.size ();
355    int nombre  = tshapes.size ();
356
357    if (nblines==0 || nombre==0)
358       return HERR;
359
360    if (nombre != 1 && nombre != nblines)
361       return HERR;
362
363    for (int ns = 0 ; ns < nombre ; ns++)
364        {
365        if (tshapes[ns] == NULL)
366           {
367           sprintf (cnum, "%d", ns);
368           putError (W_ASSO_LINE5, cnum);
369           return HERR;
370           }
371        }
372
373    NewShape*  geom = tshapes [0];
374    EdgeShapes buf_lines;
375    glines.clear ();
376    gsens .clear ();
377    for (int ns = 0 ; ns < nblines ; ns++)
378        {
379        if (nombre > 1)
380            geom = tshapes [ns];
381        EdgeShape* shape = geom->findEdge (subid[ns]);
382        if (shape==NULL)
383           {
384           sprintf  (cnum, "%d", ns);
385           putError (W_ASSO_LINE5, cnum);
386           return HERR;
387           }
388        buf_lines.push_back (shape);
389        }
390
391    Real3      pnext;
392    EdgeShape* gnext    = buf_lines[0];
393    buf_lines[0] = NULL;
394    int  reste   = nblines - 1;
395    int  rev     = inv;
396
397    lgtotale = gnext->getLength();
398    glines.push_back (gnext);
399    gsens .push_back (inv);
400
401    for (int nro = 0 ; nro < reste ; nro++)
402        {
403        double param = 1-rev;
404        gnext->getPoint (param, pnext);
405        gnext = find_line (buf_lines, pnext, rev);
406        if (gnext == NULL)
407           return HERR;
408        lgtotale += gnext->getLength();
409        glines.push_back (gnext);
410        gsens .push_back (rev);
411        }
412
413    if (closed)
414       {
415       EdgeShape* gfirst = glines[0];
416       gfirst->getPoint (1-inv, pnext);
417       int ext = gnext->onExtremity (pnext);
418       if (ext<0)
419          return HERR;
420       }
421    return HOK;
422 }
423 // ====================================================== sortEdges
424 int Document::sortEdges (Vertex* vfirst, Edges& mline, Edges& tab_edge,
425                           IntVector& tab_sens)
426 {
427    char cnum [8];
428    bool closed = vfirst!=NULL;
429
430    int nbedges = mline.size ();
431    if (nbedges==0)
432       return HERR;
433
434    Edge* mstart = mline[0];    // Coherence ancienne version
435                 // Contour ferme :
436                 // Le vertex de depart n'appartient pas a l'edge de depart
437    int istart = mstart->index (vfirst);
438    if (closed && istart == NOTHING)
439       {
440       putError (W_ASSO_LINE2, vfirst->getName());
441       return HERR;
442       }
443
444    tab_edge.clear();
445    tab_sens.clear();
446    Edges  buf_edge;
447    for (int nro = 0 ; nro < nbedges ; nro++)
448        {
449        Edge* edge = mline[nro];
450        if (edge == NULL)
451           {
452           sprintf (cnum, "%d", nro);
453           putError (W_ASSO_LINE5, cnum);
454           return HERR;
455           }
456        buf_edge.push_back (edge);
457        }
458
459    Vertex* vnext = NULL;
460    Edge*   enext = mstart;
461    int sens      = istart;
462    int reste     = nbedges - 1;
463    tab_edge.push_back (mstart);
464    buf_edge[0]  = NULL;
465
466    if (closed)
467       {
468       tab_sens.push_back (istart);
469       }
470    else
471       {
472       istart = V_AMONT;
473       vnext  = mstart->getVertex (1-istart);
474       enext  = find_edge (buf_edge, vnext, sens);
475       if (enext==NULL)
476          {
477          istart = 1-istart;
478          vnext  = mstart->getVertex (1-istart);
479          enext  = find_edge (buf_edge, vnext, sens);
480          }
481       if (enext==NULL)
482          return HERR;
483       tab_sens.push_back (istart);
484       tab_edge.push_back (enext);
485       tab_sens.push_back (sens);
486       reste--;
487       }
488
489    for (int nro = 0 ; nro < reste ; nro++)
490        {
491        vnext = enext->getVertex (1 - sens);
492        enext = find_edge (buf_edge, vnext, sens);
493        if (enext == NULL)
494           return HERR;
495        tab_edge.push_back (enext);
496        tab_sens.push_back (sens);
497        }
498
499    istart = tab_edge [nbedges-1]->index (vfirst);
500    if (closed && istart == NOTHING)
501       {
502       putError (W_ASSO_LINE2, vfirst->getName());
503       return HERR;
504       }
505
506    return HOK;
507 }
508 // ====================================================== checkAssociations
509 int Document::checkAssociations ()
510 {
511    int nombre = countUsedEdge();
512    for (int ned=0 ; ned<nombre ; ++ned)
513        {
514        Edge* edge = getUsedEdge (ned);
515        int ier = edge->checkAssociation ();
516        // if (ier != HOK) return ier;
517        }
518
519    return HOK;
520 }
521 END_NAMESPACE_HEXA