Salome HOME
Updated copyright comment
[modules/hexablock.git] / src / HEXABLOCK / HexDocument_asso.cxx
1
2 // C++ : Associations dans le document
3
4 // Copyright (C) 2009-2024  CEA, EDF
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, or (at your option) any later version.
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 #include "HexPropagation.hxx"
29
30 #include <map>
31
32 BEGIN_NAMESPACE_HEXA
33
34 static bool db = on_debug ();  // == getenv ("HEXA_DB") > 0
35
36
37 int vertexInLine (Vertex* vfirst, Edges& mline, std::vector<int> &tsens);
38 // ====================================================== vertexInLine
39 int vertexInLine (Vertex* vfirst, Edges& mline, std::vector<int> &tsens)
40 {
41    int nbseg = mline.size ();
42
43    for (int ned = 0 ; ned<nbseg ; ned++)
44        {
45        if (tsens [ned] == V_TWO)
46           for (int ns=V_AMONT; ns<=V_AVAL ; ns++)
47               {
48               if (mline[ned]->getVertex (ns) == vfirst)
49                  {
50                  tsens [ned] = ns;
51                  return ned;
52                  }
53               }
54        }
55
56    return NOTHING;
57 }
58 // ====================================================== clearAssociation
59 void Document::clearAssociation ()
60 {
61    clearAssoVertices ();
62    clearAssoEdges ();
63    clearAssoQuads ();
64 }
65 // ====================================================== clearAssociation (t)
66 int Document::clearAssociation (EnumElt type)
67 {
68    switch (type)
69       {
70       case EL_VERTEX  :
71            clearAssoVertices ();
72            break;
73       case EL_EDGE  :
74            clearAssoEdges ();
75            break;
76       case EL_QUAD  :
77            clearAssoQuads ();
78            break;
79       default : return HERR;
80       }
81
82    return HOK;
83 }
84 // ====================================================== clearAssoVertices
85 void Document::clearAssoVertices ()
86 {
87    for (EltBase* elt = doc_first_elt[EL_VERTEX]->next (); elt!=NULL;
88                  elt = elt->next())
89        {
90        Vertex* elem = static_cast <Vertex*> (elt);
91        if (elem->isValid ())
92            elem->clearAssociation ();
93        }
94 }
95 // ====================================================== clearAssoEdges
96 void Document::clearAssoEdges ()
97 {
98    for (EltBase* elt = doc_first_elt[EL_EDGE]->next (); elt!=NULL;
99                  elt = elt->next())
100        {
101        Edge* elem = static_cast <Edge*> (elt);
102        if (elem->isValid ())
103            elem->clearAssociation ();
104        }
105 }
106 // ====================================================== clearAssoQuads
107 void Document::clearAssoQuads ()
108 {
109    for (EltBase* elt = doc_first_elt[EL_QUAD]->next (); elt!=NULL;
110                  elt = elt->next())
111        {
112        Quad* elem = static_cast <Quad*> (elt);
113        if (elem->isValid ())
114            elem->clearAssociation ();
115        }
116 }
117 // ====================================================== addShape (1)
118 NewShape* Document::addShape (TopoDS_Shape& topo, cpchar name)
119 {
120    NewShape* shape = new NewShape (this);
121    doc_tab_shape.push_back (shape);
122
123    shape->setName  (name);
124    shape->setShape (topo);
125    return shape;
126 }
127 // ====================================================== addShape (2)
128 NewShape* Document::addShape (cpchar name, EnumShape type)
129 {
130    NewShape* shape = new NewShape (this, type);
131    doc_tab_shape.push_back (shape);
132
133    shape->setName  (name);
134    return shape;
135 }
136 // ====================================================== addCloud
137 void Document::addCloud ()
138 {
139    doc_cloud = new NewShape (this, SH_CLOUD);
140    doc_cloud->setName  ("cloud");
141
142    doc_tab_shape.push_back (doc_cloud);
143 }
144 // ====================================================== getShape
145 NewShape* Document::getShape (int nro)
146 {
147    int nbre = doc_tab_shape.size ();
148    if (nro < 0 || nro >= nbre)
149       return NULL;
150
151    return doc_tab_shape [nro];
152 }
153 // ====================================================== getFirstExplicitShape
154 cpchar Document::getFirstExplicitShape()
155 {
156    int nbre = doc_tab_shape.size ();
157    for (int nro=0 ; nro < nbre ; ++nro)
158        {
159        NewShape* shape = doc_tab_shape [nro];
160        if (shape!= NULL && shape->getOrigin()==SH_IMPORT)
161           return shape->getBrep ();
162        }
163
164    return NULL;
165 }
166 // ====================================================== findShape
167 NewShape* Document::findShape (rcstring nom)
168 {
169    int nbre = doc_tab_shape.size ();
170    for (int nro=0 ; nro<nbre ; ++nro)
171        if (nom == doc_tab_shape [nro]->getName())
172           return  doc_tab_shape [nro];
173
174    return NULL;
175 }
176 // ====================================================== find_line
177 EdgeShape* find_line (EdgeShapes& gline, double* point, int& sens)
178 {
179    int nbseg = gline.size ();
180
181    for (int ned = 0 ; ned<nbseg ; ned++)
182        {
183        EdgeShape* edge = gline [ned];
184        if (edge!=NULL)
185           {
186           sens = edge->onExtremity (point);
187           if (sens >=0)
188              {
189              gline [ned] = NULL;
190              return edge;
191              }
192           }
193        }
194    return NULL;
195 }
196 // ====================================================== find_edge
197 Edge* find_edge (Edges& mline, Vertex* vfirst, int& sens)
198 {
199    int nbseg = mline.size ();
200
201    for (int ned = 0 ; ned<nbseg ; ned++)
202        {
203        Edge* edge = mline [ned];
204        if (edge!=NULL)
205           {
206           sens = edge->index (vfirst);
207           if (sens >=0)
208              {
209              mline [ned] = NULL;
210              return edge;
211              }
212           }
213        }
214    return NULL;
215 }
216 // ====================================================== associateOpenedLine
217 int Document::associateOpenedLine (Edges  mline, NewShapes gline,
218                                    IntVector tabid,
219                                    double pstart, double pend)
220 {
221   std::cout << "_________________________________ Asso Open Line"
222             << " ed=" << mline.size()
223             << " sh=" << tabid.size()
224             << std::endl;
225    int ier = associateLine (NULL, mline, gline, tabid, pstart, pend, false);
226    return ier;
227 }
228 // ====================================================== associateClosedLine
229 int Document::associateClosedLine (Vertex* vfirst,   Edges  mline,
230                                    NewShapes gline, IntVector tabid,
231                                    double pstart, bool inv)
232 {
233    if (vfirst == NULL)
234       {
235       putError (W_ASSO_LINE3);
236       return HERR;
237       }
238
239    std::cout << "_________________________________ Asso Closed Line"
240              << " first=" << vfirst->getName()
241              << " ed=" << mline.size()
242              << " sh=" << tabid.size()
243              << " inv=" << inv
244              << std::endl;
245    int ier = associateLine (vfirst, mline, gline, tabid, pstart, 1.0, inv);
246    PutData (ier);
247    return ier;
248 }
249 // ====================================================== associateLine
250 int Document::associateLine (Vertex* vfirst, Edges& mline,
251                              NewShapes& tshapes, IntVector& subid,
252                              double pstart, double pend, bool inv)
253 {
254    EdgeShapes glines;
255    Edges      tedges;
256    IntVector  gsens, tsens;
257    double     lgtotale;
258
259    bool closed = vfirst!=NULL;
260    int ier = sortShapes (tshapes, subid, closed, inv, pstart, pend,
261                          glines,  gsens, lgtotale);
262    if (ier != HOK)
263        return ier;
264
265    ier = sortEdges (vfirst, mline, tedges, tsens);
266    if (ier != HOK)
267        return ier;
268
269    int nbedges  = tedges.size();
270    int nblines  = glines.size();
271
272    EdgeShape* gstart  = glines [0];
273    EdgeShape* gend    = glines [nblines-1];
274    bool       boucle  = closed && nblines==1;
275
276    double abstart = inv ? (1-pstart) : pstart;
277    if (NOT closed)
278       {
279       bool   rev     = gsens  [nblines-1]!=0;
280       double abend   = rev ?  pend      : (1-pend);
281       lgtotale = lgtotale - abstart * gstart->getLength()
282                           - abend   * gend  ->getLength();
283       }
284                                               // 1er point
285    Real3  point;
286    gstart->getPoint (pstart, point);
287    int vsid     = doc_cloud->addPoint  (point);
288    Vertex* node = tedges[0]->getVertex (tsens[0]);
289    node->setAssociation (doc_cloud, vsid);
290
291    double lgedge = lgtotale/nbedges;
292    double smax   = gstart->getLength()*(1-abstart);
293    double emax   = lgedge;
294    double pdeb   = pstart;
295    double ablast = 0;
296    double tol    = 1e-2;
297
298    int nsh   = 0;
299    int ned   = 0;
300    while (ned < nbedges && nsh < nblines)
301        {
302        EdgeShape* shape = glines [nsh];
303        Edge*      edge  = tedges [ned];
304        bool       grev  = gsens  [nsh]==1;
305        bool    av_shape = smax < emax + tol;
306        bool    av_edge  = emax < smax + tol;
307        bool    vassoc   = av_edge && NOT (closed && ned == nbedges-1);
308        double  pfin     = 1;
309        double  lgshape  = shape->getLength ();
310
311        double abscisse = std::min (emax, smax);
312        double decal    = (abscisse-ablast) / lgshape;
313        if (grev)
314           {
315           pfin = pdeb - decal;
316           if (pfin < 0.0) pfin = 0;
317           }
318        else
319           {
320           pfin = pdeb + decal;
321           if (pfin > 1.0) pfin = 1;
322           }
323
324        edge->addAssociation (shape, pdeb, pfin);
325
326        if (vassoc)
327           {
328           shape->getPoint (pfin, point);
329           vsid  = doc_cloud->addPoint  (point);
330           node  = edge  ->getVertex (1-tsens[ned]);
331
332           node->setAssociation (doc_cloud, vsid);
333           }
334        ablast = abscisse;
335        pdeb   = pfin;
336                        // On incremente les edges
337        if (av_edge)
338           {
339           ned ++;
340           emax += lgedge;
341           }
342                        // On incremente les shapes
343        if (av_shape)
344           {
345           pdeb = 0;
346           if (boucle)
347              smax = shape->getLength ();
348           else
349              {
350              nsh ++;
351              if (nsh<nblines)
352                  smax += glines[nsh]->getLength();
353              }
354           }
355        }
356
357    return HOK;
358 }
359 // ====================================================== sortShapes
360 int Document::sortShapes (NewShapes&  tshapes, IntVector& subid, bool closed,
361                       bool inv, double pstart, double pend,
362                       EdgeShapes& glines,  IntVector& gsens, double& lgtotale)
363 {
364    char cnum [8];
365    int nblines = subid.size ();
366    int nombre  = tshapes.size ();
367
368    if (nblines==0 || nombre==0)
369       return HERR;
370
371    if (nombre != 1 && nombre != nblines)
372       return HERR;
373
374    for (int ns = 0 ; ns < nombre ; ns++)
375        {
376        if (tshapes[ns] == NULL)
377           {
378           sprintf (cnum, "%d", ns);
379           putError (W_ASSO_LINE5, cnum);
380           return HERR;
381           }
382        }
383
384    NewShape*  geom = tshapes [0];
385    EdgeShapes buf_lines;
386    glines.clear ();
387    gsens .clear ();
388    for (int ns = 0 ; ns < nblines ; ns++)
389        {
390        if (nombre > 1)
391            geom = tshapes [ns];
392        EdgeShape* shape = geom->findEdge (subid[ns]);
393        if (shape==NULL)
394           {
395           sprintf  (cnum, "%d", ns);
396           putError (W_ASSO_LINE5, cnum);
397           return HERR;
398           }
399        buf_lines.push_back (shape);
400        }
401
402    Real3      pnext;
403    EdgeShape* gnext    = buf_lines[0];
404    buf_lines[0] = NULL;
405    int  reste   = nblines - 1;
406    int  rev     = inv;
407
408    lgtotale = gnext->getLength();
409    glines.push_back (gnext);
410    gsens .push_back (inv);
411
412    for (int nro = 0 ; nro < reste ; nro++)
413        {
414        double param = 1-rev;
415        gnext->getPoint (param, pnext);
416        gnext = find_line (buf_lines, pnext, rev);
417        if (gnext == NULL)
418           return HERR;
419        lgtotale += gnext->getLength();
420        glines.push_back (gnext);
421        gsens .push_back (rev);
422        }
423
424    if (closed)
425       {
426       EdgeShape* gfirst = glines[0];
427       gfirst->getPoint (1-inv, pnext);
428       int ext = gnext->onExtremity (pnext);
429       if (ext<0)
430          return HERR;
431       }
432    return HOK;
433 }
434 // ====================================================== sortEdges
435 int Document::sortEdges (Vertex* vfirst, Edges& mline, Edges& tab_edge,
436                           IntVector& tab_sens)
437 {
438    char cnum [8];
439    bool closed = vfirst!=NULL;
440
441    int nbedges = mline.size ();
442    if (nbedges==0)
443       return HERR;
444
445    Edge* mstart = mline[0];    // Coherence ancienne version
446                 // Contour ferme :
447                 // Le vertex de depart n'appartient pas a l'edge de depart
448    int istart = mstart->index (vfirst);
449    if (closed && istart == NOTHING)
450       {
451       putError (W_ASSO_LINE2, vfirst->getName());
452       return HERR;
453       }
454
455    tab_edge.clear();
456    tab_sens.clear();
457    Edges  buf_edge;
458    for (int nro = 0 ; nro < nbedges ; nro++)
459        {
460        Edge* edge = mline[nro];
461        if (edge == NULL)
462           {
463           sprintf (cnum, "%d", nro);
464           putError (W_ASSO_LINE5, cnum);
465           return HERR;
466           }
467        buf_edge.push_back (edge);
468        }
469
470    Vertex* vnext = NULL;
471    Edge*   enext = mstart;
472    int sens      = istart;
473    int reste     = nbedges - 1;
474    tab_edge.push_back (mstart);
475    buf_edge[0]  = NULL;
476
477    if (closed)
478       {
479       tab_sens.push_back (istart);
480       }
481    else
482       {
483       istart = V_AMONT;
484       vnext  = mstart->getVertex (1-istart);
485       enext  = find_edge (buf_edge, vnext, sens);
486       if (enext==NULL)
487          {
488          istart = 1-istart;
489          vnext  = mstart->getVertex (1-istart);
490          enext  = find_edge (buf_edge, vnext, sens);
491          }
492       if (enext==NULL)
493          return HERR;
494       tab_sens.push_back (istart);
495       tab_edge.push_back (enext);
496       tab_sens.push_back (sens);
497       reste--;
498       }
499
500    for (int nro = 0 ; nro < reste ; nro++)
501        {
502        vnext = enext->getVertex (1 - sens);
503        enext = find_edge (buf_edge, vnext, sens);
504        if (enext == NULL)
505           return HERR;
506        tab_edge.push_back (enext);
507        tab_sens.push_back (sens);
508        }
509
510    istart = tab_edge [nbedges-1]->index (vfirst);
511    if (closed && istart == NOTHING)
512       {
513       putError (W_ASSO_LINE2, vfirst->getName());
514       return HERR;
515       }
516
517    return HOK;
518 }
519 // ====================================================== checkAssociations
520 int Document::checkAssociations ()
521 {
522    int nombre = countUsedEdge();
523    int nberrors = 0;
524    for (int ned=0 ; ned<nombre ; ++ned)
525        {
526        Edge* edge = getUsedEdge (ned);
527        int ier = edge->checkAssociation ();
528        if (ier != HOK) nberrors ++;
529        }
530
531    std::cout << " ... Check edges assotiations : " << nberrors
532              << " error(s)." << std::endl;
533
534    if (nberrors>0) return HERR;
535       else         return HOK;
536 }
537 // ====================================================== addLaws
538 int Document::addLaws (double lgmoy, bool usemax)
539 {
540    const double Epsilon   = 1e-6;
541    const double Precision = 1e-2;
542    const double BigNumber = 1e+36;
543
544    std::map <int, Law*>    existing_law;
545    std::map <int, Law*> :: iterator iter;
546
547    if (lgmoy<=Epsilon)
548       return HERR;
549
550    int nbprop = countPropagation();
551    for (int np=0 ; np<nbprop ; ++np)
552        {
553        Propagation* prop      = getPropagation (np);
554        const Edges& tab_edges = prop->getEdges ();
555        double lgref = usemax ? 0 : BigNumber;
556        int  nbedges = tab_edges.size();
557        for (int ned=0 ; ned<nbedges ; ++ned)
558            {
559            Edge*  edge = tab_edges [ned];
560            double lg   = edge->getAssoLen ();
561            if (usemax)
562               lgref = std::max (lgref, lg);
563            else
564               lgref = std::min (lgref, lg);
565            }
566         lgref        = lgref / lgmoy;
567         int    nbcut = (int) lgref; 
568         double delta =  lgref - (double) nbcut; 
569         if (NOT usemax || (delta < Precision))
570             nbcut --;
571
572         iter = existing_law.find (nbcut);
573         if (iter == existing_law.end())
574            {
575            char name [2];
576            sprintf (name, "u_%02d", nbcut);
577            existing_law [nbcut] = addLaw (name, nbcut);
578            }
579        prop->setLaw (existing_law [nbcut]);
580        }
581    return HOK;
582 }
583 END_NAMESPACE_HEXA