Salome HOME
Committing in .
[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 // ====================================================== getFirstExplicitShape
155 cpchar Document::getFirstExplicitShape()
156 {
157    int nbre = doc_tab_shape.size ();
158    for (int nro=0 ; nro < nbre ; ++nro)
159        {
160        NewShape* shape = doc_tab_shape [nro];
161        if (shape!= NULL && shape->getOrigin()==SH_IMPORT)
162           return shape->getBrep ();
163        }
164
165    return NULL;
166 }
167 // ====================================================== findShape
168 NewShape* Document::findShape (rcstring nom)
169 {
170    int nbre = doc_tab_shape.size ();
171    for (int nro=0 ; nro<nbre ; ++nro)
172        if (nom == doc_tab_shape [nro]->getName())
173           return  doc_tab_shape [nro];
174
175    return NULL;
176 }
177 // ====================================================== find_line
178 EdgeShape* find_line (EdgeShapes& gline, double* point, int& sens)
179 {
180    int nbseg = gline.size ();
181
182    for (int ned = 0 ; ned<nbseg ; ned++)
183        {
184        EdgeShape* edge = gline [ned];
185        if (edge!=NULL)
186           {
187           sens = edge->onExtremity (point);
188           if (sens >=0)
189              {
190              gline [ned] = NULL;
191              return edge;
192              }
193           }
194        }
195    return NULL;
196 }
197 // ====================================================== find_edge
198 Edge* find_edge (Edges& mline, Vertex* vfirst, int& sens)
199 {
200    int nbseg = mline.size ();
201
202    for (int ned = 0 ; ned<nbseg ; ned++)
203        {
204        Edge* edge = mline [ned];
205        if (edge!=NULL)
206           {
207           sens = edge->index (vfirst);
208           if (sens >=0)
209              {
210              mline [ned] = NULL;
211              return edge;
212              }
213           }
214        }
215    return NULL;
216 }
217 // ====================================================== associateOpenedLine
218 int Document::associateOpenedLine (Edges  mline, NewShapes gline,
219                                    IntVector tabid,
220                                    double pstart, double pend)
221 {
222    cout << "_________________________________ Asso Open Line"
223         << " ed=" << mline.size()
224         << " sh=" << tabid.size()
225         << endl;
226    int ier = associateLine (NULL, mline, gline, tabid, pstart, pend, false);
227    return ier;
228 }
229 // ====================================================== associateClosedLine
230 int Document::associateClosedLine (Vertex* vfirst,   Edges  mline,
231                                    NewShapes gline, IntVector tabid,
232                                    double pstart, bool inv)
233 {
234    if (vfirst == NULL)
235       {
236       putError (W_ASSO_LINE3);
237       return HERR;
238       }
239
240    cout << "_________________________________ Asso Closed Line"
241         << " first=" << vfirst->getName()
242         << " ed=" << mline.size()
243         << " sh=" << tabid.size()
244         << " inv=" << inv
245         << endl;
246    int ier = associateLine (vfirst, mline, gline, tabid, pstart, 1.0, inv);
247    PutData (ier);
248    return ier;
249 }
250 // ====================================================== associateLine
251 int Document::associateLine (Vertex* vfirst, Edges& mline,
252                              NewShapes& tshapes, IntVector& subid,
253                              double pstart, double pend, bool inv)
254 {
255    EdgeShapes glines;
256    Edges      tedges;
257    IntVector  gsens, tsens;
258    double     lgtotale;
259
260    bool closed = vfirst!=NULL;
261    int ier = sortShapes (tshapes, subid, closed, inv, pstart, pend,
262                          glines,  gsens, lgtotale);
263    if (ier != HOK)
264        return ier;
265
266    ier = sortEdges (vfirst, mline, tedges, tsens);
267    if (ier != HOK)
268        return ier;
269
270    int nbedges  = tedges.size();
271    int nblines  = glines.size();
272
273    EdgeShape* gstart  = glines [0];
274    EdgeShape* gend    = glines [nblines-1];
275    bool       boucle  = closed && nblines==1;
276
277    double abstart = inv ? (1-pstart) : pstart;
278    if (NOT closed)
279       {
280       bool   rev     = gsens  [nblines-1]!=0;
281       double abend   = rev ?  pend      : (1-pend);
282       lgtotale = lgtotale - abstart * gstart->getLength()
283                           - abend   * gend  ->getLength();
284       }
285                                               // 1er point
286    Real3  point;
287    gstart->getPoint (pstart, point);
288    int vsid     = doc_cloud->addPoint  (point);
289    Vertex* node = tedges[0]->getVertex (tsens[0]);
290    node->setAssociation (doc_cloud, vsid);
291
292    double lgedge = lgtotale/nbedges;
293    double smax   = gstart->getLength()*(1-abstart);
294    double emax   = lgedge;
295    double pdeb   = pstart;
296    double ablast = 0;
297    double tol    = 1e-2;
298
299    int nsh   = 0;
300    int ned   = 0;
301    while (ned < nbedges && nsh < nblines)
302        {
303        EdgeShape* shape = glines [nsh];
304        Edge*      edge  = tedges [ned];
305        bool       grev  = gsens  [nsh]==1;
306        bool    av_shape = smax < emax + tol;
307        bool    av_edge  = emax < smax + tol;
308        bool    vassoc   = av_edge && NOT (closed && ned == nbedges-1);
309        double  pfin     = 1;
310        double  lgshape  = shape->getLength ();
311
312        double abscisse = std::min (emax, smax);
313        double decal    = (abscisse-ablast) / lgshape;
314        if (grev)
315           {
316           pfin = pdeb - decal;
317           if (pfin < 0.0) pfin = 0;
318           }
319        else
320           {
321           pfin = pdeb + decal;
322           if (pfin > 1.0) pfin = 1;
323           }
324
325        edge->addAssociation (shape, pdeb, pfin);
326
327        if (vassoc)
328           {
329           shape->getPoint (pfin, point);
330           vsid  = doc_cloud->addPoint  (point);
331           node  = edge  ->getVertex (1-tsens[ned]);
332
333           node->setAssociation (doc_cloud, vsid);
334           }
335        ablast = abscisse;
336        pdeb   = pfin;
337                        // On incremente les edges
338        if (av_edge)
339           {
340           ned ++;
341           emax += lgedge;
342           }
343                        // On incremente les shapes
344        if (av_shape)
345           {
346           pdeb = 0;
347           if (boucle)
348              smax = shape->getLength ();
349           else
350              {
351              nsh ++;
352              if (nsh<nblines)
353                  smax += glines[nsh]->getLength();
354              }
355           }
356        }
357
358    return HOK;
359 }
360 // ====================================================== sortShapes
361 int Document::sortShapes (NewShapes&  tshapes, IntVector& subid, bool closed,
362                       bool inv, double pstart, double pend,
363                       EdgeShapes& glines,  IntVector& gsens, double& lgtotale)
364 {
365    char cnum [8];
366    int nblines = subid.size ();
367    int nombre  = tshapes.size ();
368
369    if (nblines==0 || nombre==0)
370       return HERR;
371
372    if (nombre != 1 && nombre != nblines)
373       return HERR;
374
375    for (int ns = 0 ; ns < nombre ; ns++)
376        {
377        if (tshapes[ns] == NULL)
378           {
379           sprintf (cnum, "%d", ns);
380           putError (W_ASSO_LINE5, cnum);
381           return HERR;
382           }
383        }
384
385    NewShape*  geom = tshapes [0];
386    EdgeShapes buf_lines;
387    glines.clear ();
388    gsens .clear ();
389    for (int ns = 0 ; ns < nblines ; ns++)
390        {
391        if (nombre > 1)
392            geom = tshapes [ns];
393        EdgeShape* shape = geom->findEdge (subid[ns]);
394        if (shape==NULL)
395           {
396           sprintf  (cnum, "%d", ns);
397           putError (W_ASSO_LINE5, cnum);
398           return HERR;
399           }
400        buf_lines.push_back (shape);
401        }
402
403    Real3      pnext;
404    EdgeShape* gnext    = buf_lines[0];
405    buf_lines[0] = NULL;
406    int  reste   = nblines - 1;
407    int  rev     = inv;
408
409    lgtotale = gnext->getLength();
410    glines.push_back (gnext);
411    gsens .push_back (inv);
412
413    for (int nro = 0 ; nro < reste ; nro++)
414        {
415        double param = 1-rev;
416        gnext->getPoint (param, pnext);
417        gnext = find_line (buf_lines, pnext, rev);
418        if (gnext == NULL)
419           return HERR;
420        lgtotale += gnext->getLength();
421        glines.push_back (gnext);
422        gsens .push_back (rev);
423        }
424
425    if (closed)
426       {
427       EdgeShape* gfirst = glines[0];
428       gfirst->getPoint (1-inv, pnext);
429       int ext = gnext->onExtremity (pnext);
430       if (ext<0)
431          return HERR;
432       }
433    return HOK;
434 }
435 // ====================================================== sortEdges
436 int Document::sortEdges (Vertex* vfirst, Edges& mline, Edges& tab_edge,
437                           IntVector& tab_sens)
438 {
439    char cnum [8];
440    bool closed = vfirst!=NULL;
441
442    int nbedges = mline.size ();
443    if (nbedges==0)
444       return HERR;
445
446    Edge* mstart = mline[0];    // Coherence ancienne version
447                 // Contour ferme :
448                 // Le vertex de depart n'appartient pas a l'edge de depart
449    int istart = mstart->index (vfirst);
450    if (closed && istart == NOTHING)
451       {
452       putError (W_ASSO_LINE2, vfirst->getName());
453       return HERR;
454       }
455
456    tab_edge.clear();
457    tab_sens.clear();
458    Edges  buf_edge;
459    for (int nro = 0 ; nro < nbedges ; nro++)
460        {
461        Edge* edge = mline[nro];
462        if (edge == NULL)
463           {
464           sprintf (cnum, "%d", nro);
465           putError (W_ASSO_LINE5, cnum);
466           return HERR;
467           }
468        buf_edge.push_back (edge);
469        }
470
471    Vertex* vnext = NULL;
472    Edge*   enext = mstart;
473    int sens      = istart;
474    int reste     = nbedges - 1;
475    tab_edge.push_back (mstart);
476    buf_edge[0]  = NULL;
477
478    if (closed)
479       {
480       tab_sens.push_back (istart);
481       }
482    else
483       {
484       istart = V_AMONT;
485       vnext  = mstart->getVertex (1-istart);
486       enext  = find_edge (buf_edge, vnext, sens);
487       if (enext==NULL)
488          {
489          istart = 1-istart;
490          vnext  = mstart->getVertex (1-istart);
491          enext  = find_edge (buf_edge, vnext, sens);
492          }
493       if (enext==NULL)
494          return HERR;
495       tab_sens.push_back (istart);
496       tab_edge.push_back (enext);
497       tab_sens.push_back (sens);
498       reste--;
499       }
500
501    for (int nro = 0 ; nro < reste ; nro++)
502        {
503        vnext = enext->getVertex (1 - sens);
504        enext = find_edge (buf_edge, vnext, sens);
505        if (enext == NULL)
506           return HERR;
507        tab_edge.push_back (enext);
508        tab_sens.push_back (sens);
509        }
510
511    istart = tab_edge [nbedges-1]->index (vfirst);
512    if (closed && istart == NOTHING)
513       {
514       putError (W_ASSO_LINE2, vfirst->getName());
515       return HERR;
516       }
517
518    return HOK;
519 }
520 // ====================================================== checkAssociations
521 int Document::checkAssociations ()
522 {
523    int nombre = countUsedEdge();
524    int nberrors = 0;
525    for (int ned=0 ; ned<nombre ; ++ned)
526        {
527        Edge* edge = getUsedEdge (ned);
528        int ier = edge->checkAssociation ();
529        if (ier != HOK) nberrors ++;
530        }
531
532    cout << " ... Check edges assotiations : " << nberrors
533         << " error(s)." << endl;
534
535    if (nberrors>0) return HERR;
536       else         return HOK;
537 }
538 // ====================================================== addLaws
539 int Document::addLaws (double lgmoy, bool usemax)
540 {
541    const double Epsilon   = 1e-6;
542    const double Precision = 1e-2;
543    const double BigNumber = 1e+36;
544
545    std::map <int, Law*>    existing_law;
546    std::map <int, Law*> :: iterator iter;
547
548    if (lgmoy<=Epsilon)
549       return HERR;
550
551    int nbprop = countPropagation();
552    for (int np=0 ; np<nbprop ; ++np)
553        {
554        Propagation* prop      = getPropagation (np);
555        const Edges& tab_edges = prop->getEdges ();
556        double lgref = usemax ? 0 : BigNumber;
557        int  nbedges = tab_edges.size();
558        for (int ned=0 ; ned<nbedges ; ++ned)
559            {
560            Edge*  edge = tab_edges [ned];
561            double lg   = edge->getAssoLen ();
562            if (usemax)
563               lgref = std::max (lgref, lg);
564            else
565               lgref = std::min (lgref, lg);
566            }
567         lgref        = lgref / lgmoy;
568         int    nbcut = (int) lgref; 
569         double delta =  lgref - (double) nbcut; 
570         if (NOT usemax || (delta < Precision))
571             nbcut --;
572
573         iter = existing_law.find (nbcut);
574         if (iter == existing_law.end())
575            {
576            char name [2];
577            sprintf (name, "u_%02d", nbcut);
578            existing_law [nbcut] = addLaw (name, nbcut);
579            }
580        prop->setLaw (existing_law [nbcut]);
581        }
582    return HOK;
583 }
584 END_NAMESPACE_HEXA