Salome HOME
a73f4779840e9cc9c809512a845be71924ff69e9
[modules/shaper.git] / src / PartSet / PartSet_FieldStepPrs.cpp
1 // Copyright (C) 2014-2022  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "PartSet_FieldStepPrs.h"
21
22 #include <ModuleBase_Preferences.h>
23
24 #include <CollectionPlugin_Field.h>
25
26 #include <ModelAPI_AttributeSelectionList.h>
27 #include <ModelAPI_AttributeIntArray.h>
28 #include <ModelAPI_AttributeStringArray.h>
29
30 #include <SUIT_ResourceMgr.h>
31
32 #include <AIS_ColorScale.hxx>
33 #include <Prs3d_Drawer.hxx>
34 #include <Prs3d_PointAspect.hxx>
35 #include <BRep_Tool.hxx>
36 #include <BRepAdaptor_Surface.hxx>
37 #include <TopoDS.hxx>
38 #include <TopoDS_Vertex.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <Graphic3d_Text.hxx>
41
42
43 IMPLEMENT_STANDARD_RTTIEXT(PartSet_FieldStepPrs, ViewerData_AISShape);
44
45 #define POINT_SIZE 8
46
47
48 void emptyDeleter(ModelAPI_ResultField* /*theF*/)
49 {
50   // Do nothing
51 }
52
53 PartSet_FieldStepPrs::PartSet_FieldStepPrs(FieldStepPtr theStep)
54 : ViewerData_AISShape(TopoDS_Shape()), myStep(theStep)
55 {
56   ModelAPI_ResultField* aField = theStep->field();
57   GeomShapePtr aShapePtr = aField->shape();
58   TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
59   Set(aShape);
60
61   // Get parameters of the Field
62   // Make shared_ptr which will not delete original pointer after exit
63   std::shared_ptr<ModelAPI_ResultField> aFieldPtr(aField, emptyDeleter);
64   myFeature = ModelAPI_Feature::feature(aFieldPtr);
65
66   if (dataType() != ModelAPI_AttributeTables::STRING) {
67     Handle(Prs3d_Drawer) aDrawer = Attributes();
68     if (aDrawer->HasOwnPointAspect()) {
69       aDrawer->PointAspect()->SetTypeOfMarker(Aspect_TOM_POINT);
70       aDrawer->PointAspect()->SetScale(POINT_SIZE);
71     }
72     else
73       aDrawer->SetPointAspect(
74         new Prs3d_PointAspect(Aspect_TOM_POINT, Quantity_NOC_YELLOW, POINT_SIZE));
75   }
76   SetMaterial(Graphic3d_NOM_PLASTIC);
77 }
78
79
80 ModelAPI_AttributeTables::ValueType PartSet_FieldStepPrs::dataType() const
81 {
82   DataPtr aData = myFeature->data();
83   AttributeTablesPtr aTablesAttr = aData->tables(CollectionPlugin_Field::VALUES_ID());
84   return aTablesAttr->type();
85 }
86
87 bool PartSet_FieldStepPrs::dataRange(double& theMin, double& theMax) const
88 {
89   ModelAPI_AttributeTables::ValueType aType = dataType();
90   if ((aType == ModelAPI_AttributeTables::DOUBLE) || (aType == ModelAPI_AttributeTables::INTEGER)) {
91     range(theMin, theMax);
92     return true;
93   }
94   return false;
95 }
96
97 QList<double> PartSet_FieldStepPrs::range(double& theMin, double& theMax) const
98 {
99   ModelAPI_AttributeTables::ValueType aType = dataType();
100   DataPtr aData = myFeature->data();
101   AttributeSelectionListPtr aSelList = aData->selectionList(CollectionPlugin_Field::SELECTED_ID());
102   std::string aTypeStr = aSelList->selectionType();
103
104   int aStep = myStep->id();
105   AttributeTablesPtr aTablesAttr = aData->tables(CollectionPlugin_Field::VALUES_ID());
106   int aRows = aTablesAttr->rows();
107   int aCols = aTablesAttr->columns();
108
109   QList<double> aFieldStepData;
110   int aStart = (aTypeStr == "part")? 0:1;
111   for (int k = aStart; k < aRows; k++) { // Do not use default values
112     for (int j = 0; j < aCols; j++) {
113       ModelAPI_AttributeTables::Value aVal = aTablesAttr->value(k, j, aStep);
114       switch (aType) {
115       case ModelAPI_AttributeTables::DOUBLE:
116         aFieldStepData << aVal.myDouble;
117         break;
118       case ModelAPI_AttributeTables::INTEGER:
119         aFieldStepData << aVal.myInt;
120         break;
121       default: // [to avoid compilation warning]
122         break;
123       }
124     }
125   }
126   QList<double> aShapeData;
127   double aRangeMin = aFieldStepData.first(), aRangeMax = aFieldStepData.last();
128   if (aCols == 1) {
129     for (int aRow = 0; aRow < aRows - aStart; aRow++) {
130       double aValue = aFieldStepData.at(aRow);
131       aRangeMin = Min(aRangeMin, aValue);
132       aRangeMax = Max(aRangeMax, aValue);
133       aShapeData << aValue;
134     }
135   }
136   else {
137     for (int aRow = 0; aRow < aRows - aStart; aRow++) {
138       double aNorm = 0;
139       int aBaseIndex = aRow * aCols;
140       for (int aCol = 0; aCol < aCols; aCol++) {
141         int anIndex = aCol + aBaseIndex;
142         double aValue = aFieldStepData.at(anIndex);
143         aNorm += aValue * aValue;
144       }
145       aNorm = pow(aNorm, 0.5);
146       aRangeMin = Min(aRangeMin, aNorm);
147       aRangeMax = Max(aRangeMax, aNorm);
148       aShapeData << aNorm;
149     }
150   }
151   theMin = aRangeMin;
152   theMax = aRangeMax;
153   return aShapeData;
154 }
155
156
157 void PartSet_FieldStepPrs::Compute(const Handle(PrsMgr_PresentationManager3d)& thePrsMgr,
158   const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode)
159 {
160   SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr();
161   QColor aQColor = aResMgr->colorValue("Viewer", "scalar_bar_text_color", Qt::black);
162   Quantity_Color aLabelColor = Quantity_Color(aQColor.redF(), aQColor.greenF(), aQColor.blueF(),
163     Quantity_TOC_RGB);
164
165   ModelAPI_AttributeTables::ValueType aType = dataType();
166   DataPtr aData = myFeature->data();
167   switch (aType) {
168   case ModelAPI_AttributeTables::DOUBLE:
169   case ModelAPI_AttributeTables::INTEGER:
170   {
171     double aMin, aMax;
172     QList<double> aShapeData = range(aMin, aMax);
173
174     AttributeSelectionListPtr aSelList =
175       aData->selectionList(CollectionPlugin_Field::SELECTED_ID());
176     std::string aTypeStr = aSelList->selectionType();
177     if (aTypeStr == "part") {
178       Quantity_Color aColor;
179       if (AIS_ColorScale::FindColor(aMin, aMin, aMax, 1, aColor)) {
180         SetColor(aColor);
181       }
182     }
183     else {
184       int aNbIntertvals = aResMgr->integerValue("Viewer", "scalar_bar_nb_intervals", 20);
185       for (int i = 0; i < aSelList->size(); i++) {
186         AttributeSelectionPtr aSelection = aSelList->value(i);
187         GeomShapePtr aShapePtr = aSelection->value();
188         TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
189         double aValue = aShapeData.at(i);
190         Quantity_Color aColor;
191         if (AIS_ColorScale::FindColor(aValue, aMin, aMax, aNbIntertvals, aColor))
192           SetCustomColor(aShape, aColor);
193       }
194     }
195   }
196   break;
197   case ModelAPI_AttributeTables::BOOLEAN:
198   {
199     QList<double> aShapeData = booleanValues();
200
201     AttributeSelectionListPtr aSelList =
202       aData->selectionList(CollectionPlugin_Field::SELECTED_ID());
203     for (int i = 0; i < aSelList->size(); i++) {
204       AttributeSelectionPtr aSelection = aSelList->value(i);
205       GeomShapePtr aShapePtr = aSelection->value();
206       TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
207       double aValue = aShapeData.at(i);
208       Quantity_Color aColor;
209       if (AIS_ColorScale::FindColor(aValue, 0., 1., 2, aColor))
210         SetCustomColor(aShape, aColor);
211     }
212   }
213   break;
214   case ModelAPI_AttributeTables::STRING:
215   {
216     QStringList aValues = strings();
217     AttributeSelectionListPtr aSelList =
218       aData->selectionList(CollectionPlugin_Field::SELECTED_ID());
219     Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
220     for (int i = 0; i < aSelList->size(); i++) {
221       AttributeSelectionPtr aSelection = aSelList->value(i);
222       GeomShapePtr aShapePtr = aSelection->value();
223       TopoDS_Shape aShape = aShapePtr->impl<TopoDS_Shape>();
224       gp_Pnt aCenter;
225       if (computeMassCenter(aShape, aCenter)) {
226         Handle(Graphic3d_AspectText3d) anAspectText3d = new Graphic3d_AspectText3d();
227         anAspectText3d->SetStyle(Aspect_TOST_ANNOTATION);
228         anAspectText3d->SetColor(aLabelColor);
229         aGroup->SetPrimitivesAspect(anAspectText3d);
230
231         int aT = aResMgr->integerValue("Viewer", "scalar_bar_text_height", 14);
232         QString aString = aValues.at(i);
233         Handle(Graphic3d_Text) aText = new Graphic3d_Text(aT);
234         aText->SetText(aString.toUtf8().constData());
235         aText->SetPosition(aCenter);
236         aGroup->AddText(aText);
237       }
238     }
239   }
240   break;
241   }
242   ViewerData_AISShape::Compute(thePrsMgr, thePrs, theMode);
243 }
244
245 QList<double> PartSet_FieldStepPrs::booleanValues() const
246 {
247   DataPtr aData = myFeature->data();
248   int aStep = myStep->id();
249   AttributeTablesPtr aTablesAttr = aData->tables(CollectionPlugin_Field::VALUES_ID());
250   int aRows = aTablesAttr->rows();
251   int aCols = aTablesAttr->columns();
252   QList<int> aFieldStepData;
253   for (int k = 1; k < aRows; k++) { // Do not use default values
254     for (int j = 0; j < aCols; j++) {
255       ModelAPI_AttributeTables::Value aVal = aTablesAttr->value(k, j, aStep);
256       aFieldStepData << (aVal.myBool ? 1 : 0);
257     }
258   }
259   QList<double> aShapeData;
260   for (int aRow = 0; aRow < aRows - 1; aRow++) {
261     double aNorm = 0;
262     int aBaseIndex = aRow * aCols;
263     for (int aCol = 0; aCol < aCols; aCol++) {
264       aNorm += aFieldStepData.at(aCol + aBaseIndex);
265     }
266     aNorm /= aCols;
267     aShapeData << aNorm;
268   }
269   return aShapeData;
270 }
271
272 QStringList PartSet_FieldStepPrs::strings() const
273 {
274   DataPtr aData = myFeature->data();
275   int aStep = myStep->id();
276   AttributeTablesPtr aTablesAttr = aData->tables(CollectionPlugin_Field::VALUES_ID());
277   int aRows = aTablesAttr->rows();
278   int aCols = aTablesAttr->columns();
279   QStringList aFieldStepData;
280   for (int k = 1; k < aRows; k++) { // Do not use default values
281     for (int j = 0; j < aCols; j++) {
282       ModelAPI_AttributeTables::Value aVal = aTablesAttr->value(k, j, aStep);
283       aFieldStepData << aVal.myStr.c_str();
284     }
285   }
286   QStringList aShapeData;
287   for (int aRow = 0; aRow < aRows - 1; aRow++) {
288     QStringList aRowStrings;
289     int aBaseIndex = aRow * aCols;
290     for (int aCol = 0; aCol < aCols; aCol++) {
291       aRowStrings << aFieldStepData.at(aCol + aBaseIndex);
292     }
293     aRowStrings.join('\n');
294     aShapeData << aRowStrings;
295   }
296   return aShapeData;
297 }
298
299 bool PartSet_FieldStepPrs::computeMassCenter(const TopoDS_Shape& theShape, gp_Pnt& theCenter)
300 {
301   theCenter.SetCoord(0, 0, 0);
302   int aNbPoints = 0;
303
304   if (theShape.ShapeType() == TopAbs_EDGE) {
305     double f, l;
306     Handle(Geom_Curve) curve = BRep_Tool::Curve(TopoDS::Edge(theShape), f, l);
307     if (!curve.IsNull()) {
308       theCenter = curve->Value(0.5 * (f + l));
309       aNbPoints = 1;
310     }
311   }
312   else if (theShape.ShapeType() == TopAbs_FACE) {
313     const TopoDS_Face& F = TopoDS::Face(theShape);
314     BRepAdaptor_Surface surface(F);
315
316     TopLoc_Location L;
317     Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation(F, L);
318     if (!triangulation.IsNull() && triangulation->HasUVNodes()) {
319       gp_XY C(0, 0);
320       double A = 0;
321       const TColgp_Array1OfPnt2d& uvArray = triangulation->UVNodes();
322       const Poly_Array1OfTriangle&  trias = triangulation->Triangles();
323       int n1, n2, n3;
324       for (int iT = trias.Lower(); iT <= trias.Upper(); ++iT) {
325         trias(iT).Get(n1, n2, n3);
326         const gp_Pnt2d& uv1 = uvArray(n1);
327         const gp_Pnt2d& uv2 = uvArray(n2);
328         const gp_Pnt2d& uv3 = uvArray(n3);
329         double a = 0.5 * sqrt((uv1.X() - uv3.X()) * (uv2.Y() - uv1.Y()) -
330           (uv1.X() - uv2.X()) * (uv3.Y() - uv1.Y()));
331         C += (uv1.XY() + uv2.XY() + uv3.XY()) / 3. * a;
332         A += a;
333       }
334       if (A > std::numeric_limits<double>::min()) {
335         C /= A;
336         theCenter = surface.Value(C.X(), C.Y());
337         aNbPoints = 1;
338       }
339     }
340     if (aNbPoints == 0) {
341       theCenter = surface.Value(0.5 * (surface.FirstUParameter() + surface.LastUParameter()),
342         0.5 * (surface.FirstVParameter() + surface.LastVParameter()));
343     }
344     aNbPoints = 1;
345   }
346
347   if (aNbPoints == 0) {
348     TopExp_Explorer anExp;
349     for (anExp.Init(theShape, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
350       TopoDS_Vertex aVertex = TopoDS::Vertex(anExp.Current());
351       if (!aVertex.IsNull()) {
352         gp_Pnt aPnt = BRep_Tool::Pnt(aVertex);
353         theCenter.ChangeCoord() += aPnt.XYZ();
354         aNbPoints++;
355       }
356     }
357   }
358
359   if (aNbPoints > 0)
360     theCenter.ChangeCoord() /= (double)aNbPoints;
361
362   return aNbPoints;
363 }