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