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