Salome HOME
Correct deflection coefficient for sketch editing mode
[modules/shaper.git] / src / ModuleBase / ModuleBase_Tools.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        ModuleBase_Tools.cpp
4 // Created:     11 July 2014
5 // Author:      Vitaly Smetannikov
6
7 #include "ModuleBase_Tools.h"
8 #include <ModuleBase_ParamSpinBox.h>
9
10 #include <ModelAPI_Attribute.h>
11 #include <ModelAPI_AttributeRefAttr.h>
12 #include <ModelAPI_AttributeReference.h>
13 #include <ModelAPI_AttributeSelection.h>
14 #include <ModelAPI_Data.h>
15 #include <ModelAPI_Result.h>
16 #include <ModelAPI_ResultCompSolid.h>
17 #include <ModelAPI_ResultParameter.h>
18 #include <ModelAPI_Tools.h>
19
20 #include <TopoDS_Iterator.hxx>
21
22 #include <GeomDataAPI_Point2D.h>
23 #include <Events_Error.h>
24
25 #include <Config_PropManager.h>
26
27 #include <QWidget>
28 #include <QLayout>
29 #include <QPainter>
30 #include <QBitmap>
31 #include <QDoubleSpinBox>
32
33 #include <sstream>
34
35 const double tolerance = 1e-7;
36
37
38 namespace ModuleBase_Tools {
39
40 //******************************************************************
41
42 //******************************************************************
43
44 void adjustMargins(QWidget* theWidget)
45 {
46   if(!theWidget)
47     return;
48   adjustMargins(theWidget->layout());
49 }
50
51 void adjustMargins(QLayout* theLayout)
52 {
53   if(!theLayout)
54     return;
55   theLayout->setContentsMargins(2, 5, 2, 5);
56   theLayout->setSpacing(4);
57 }
58
59 void zeroMargins(QWidget* theWidget)
60 {
61   if(!theWidget)
62     return;
63   zeroMargins(theWidget->layout());
64 }
65
66 void zeroMargins(QLayout* theLayout)
67 {
68   if(!theLayout)
69     return;
70   theLayout->setContentsMargins(0, 0, 0, 0);
71   theLayout->setSpacing(5);
72 }
73
74 QPixmap composite(const QString& theAdditionalIcon, const QString& theIcon)
75 {
76   QImage anIcon(theIcon);
77   QImage anAditional(theAdditionalIcon);
78
79   if (anIcon.isNull())
80     return QPixmap();
81
82   int anAddWidth = anAditional.width();
83   int anAddHeight = anAditional.height();
84
85   int aWidth = anIcon.width();
86   int aHeight = anIcon.height();
87
88   int aStartWidthPos = aWidth - anAddWidth - 1;
89   int aStartHeightPos = aHeight - anAddHeight - 1;
90
91   for (int i = 0; i < anAddWidth && i + aStartWidthPos < aWidth; i++)
92   {
93     for (int j = 0; j < anAddHeight && j + aStartHeightPos < aHeight; j++)
94     {
95       if (qAlpha(anAditional.pixel(i, j)) > 0)
96         anIcon.setPixel(i + aStartWidthPos, j + aStartHeightPos, anAditional.pixel(i, j));
97     }
98   }
99   return QPixmap::fromImage(anIcon);
100 }
101
102 QPixmap lighter(const QString& theIcon, const int theLighterValue)
103 {
104   QImage anIcon(theIcon);
105   if (anIcon.isNull())
106     return QPixmap();
107
108   QImage aResult(theIcon);
109   for ( int i = 0; i < anIcon.width(); i++ )
110   {
111     for ( int j = 0; j < anIcon.height(); j++ )
112     {
113       QRgb anRgb = anIcon.pixel( i, j );
114       QColor aPixelColor(qRed(anRgb), qGreen(anRgb), qBlue(anRgb),
115                          qAlpha( aResult.pixel( i, j ) ));
116
117       QColor aLighterColor = aPixelColor.lighter(theLighterValue);
118       aResult.setPixel(i, j, qRgba( aLighterColor.red(), aLighterColor.green(),
119                                     aLighterColor.blue(), aLighterColor.alpha() ) );
120     }
121   }
122   return QPixmap::fromImage(aResult);
123 }
124
125 void setSpinText(ModuleBase_ParamSpinBox* theSpin, const QString& theText)
126 {
127   if (theSpin->text() == theText) 
128     return;
129   // In order to avoid extra text setting because it will
130   // reset cursor position in control
131   bool isBlocked = theSpin->blockSignals(true);
132   theSpin->setText(theText);
133   theSpin->blockSignals(isBlocked);
134 }
135
136 void setSpinValue(QDoubleSpinBox* theSpin, double theValue)
137 {
138   if (fabs(theSpin->value() - theValue) < tolerance)
139     return;
140   bool isBlocked = theSpin->blockSignals(true);
141   theSpin->setValue(theValue);
142   theSpin->blockSignals(isBlocked);
143 }
144
145 void setSpinValue(ModuleBase_ParamSpinBox* theSpin, double theValue)
146 {
147   if (fabs(theSpin->value() - theValue) < tolerance)
148     return;
149   bool isBlocked = theSpin->blockSignals(true);
150   theSpin->setValue(theValue);
151   theSpin->blockSignals(isBlocked);
152 }
153
154 QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo)
155 {
156   QString aFeatureStr = "feature";
157   if (!theObj.get())
158     return aFeatureStr;
159
160   std::ostringstream aPtrStr;
161   aPtrStr << "[" << theObj.get() << "]";
162
163   ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
164   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
165   if(aRes.get()) {
166     aFeatureStr.append(QString("(result%1)").arg(aPtrStr.str().c_str()).toStdString() .c_str());
167     if (aRes->isDisabled())
168       aFeatureStr.append("[disabled]");
169     if (aRes->isConcealed())
170       aFeatureStr.append("[concealed]");
171     if (ModelAPI_Tools::hasSubResults(aRes))
172       aFeatureStr.append("[hasSubResults]");
173
174     aFeature = ModelAPI_Feature::feature(aRes);
175   }
176   else
177     aFeatureStr.append(aPtrStr.str().c_str());
178
179   if (aFeature.get()) {
180     aFeatureStr.append(QString(": %1").arg(aFeature->getKind().c_str()).toStdString().c_str());
181     if (aFeature->data()->isValid()) {
182       aFeatureStr.append(QString(", name=%1").arg(aFeature->data()->name().c_str()).toStdString()
183                                                                                        .c_str());
184     }
185     if (isUseAttributesInfo) {
186       std::list<AttributePtr> anAttrs = aFeature->data()->attributes("");
187       std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
188       QStringList aValues;
189       for(; anIt != aLast; anIt++) {
190         AttributePtr anAttr = *anIt;
191         QString aValue = "not defined";
192         std::string aType = anAttr->attributeType();
193         if (aType == GeomDataAPI_Point2D::typeId()) {
194           std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
195                                                                                          anAttr);
196           if (aPoint.get())
197             aValue = QString("(%1, %2)").arg(aPoint->x()).arg(aPoint->y());
198         }
199         else if (aType == ModelAPI_AttributeRefAttr::typeId()) {
200         }
201
202         aValues.push_back(QString("%1: %2").arg(anAttr->id().c_str()).arg(aValue).toStdString().c_str());
203       }
204       if (!aValues.empty())
205         aFeatureStr.append(QString(", attributes: %1").arg(aValues.join(", ").toStdString().c_str()));
206     }
207   }
208
209   return aFeatureStr;
210 }
211
212 typedef QMap<QString, TopAbs_ShapeEnum> ShapeTypes;
213 static ShapeTypes MyShapeTypes;
214
215 TopAbs_ShapeEnum shapeType(const QString& theType)
216 {
217   if (MyShapeTypes.count() == 0) {
218     MyShapeTypes["face"] = TopAbs_FACE;
219     MyShapeTypes["faces"] = TopAbs_FACE;
220     MyShapeTypes["vertex"] = TopAbs_VERTEX;
221     MyShapeTypes["vertices"] = TopAbs_VERTEX;
222     MyShapeTypes["wire"] = TopAbs_WIRE;
223     MyShapeTypes["edge"] = TopAbs_EDGE;
224     MyShapeTypes["edges"] = TopAbs_EDGE;
225     MyShapeTypes["shell"] = TopAbs_SHELL;
226     MyShapeTypes["solid"] = TopAbs_SOLID;
227     MyShapeTypes["solids"] = TopAbs_SOLID;
228     MyShapeTypes["objects"] = TopAbs_SHAPE;
229   }
230   QString aType = theType.toLower();
231   if (MyShapeTypes.contains(aType))
232     return MyShapeTypes[aType];
233   Events_Error::send("Shape type defined in XML is not implemented!");
234   return TopAbs_SHAPE;
235 }
236
237 void checkObjects(const QObjectPtrList& theObjects, bool& hasResult, bool& hasFeature, bool& hasParameter, bool& hasSubFeature)
238 {
239   hasResult = false;
240   hasFeature = false;
241   hasParameter = false;
242   hasSubFeature = false;
243   foreach(ObjectPtr aObj, theObjects) {
244     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
245     ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
246     ResultParameterPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aResult);
247
248     hasResult |= (aResult.get() != NULL);
249     hasFeature |= (aFeature.get() != NULL);
250     hasParameter |= (aConstruction.get() != NULL);
251     if (hasFeature) 
252       hasSubFeature |= (ModelAPI_Tools::compositeOwner(aFeature) != NULL);
253     if (hasFeature && hasResult  && hasParameter && hasSubFeature)
254       break;
255   }
256 }
257
258 void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
259                                     const Handle(Prs3d_Drawer)& theDrawer)
260 {
261   if (theShape.IsNull())
262     return;
263   TopAbs_ShapeEnum aType = theShape.ShapeType();
264   if ((aType == TopAbs_EDGE) || (aType == TopAbs_WIRE)) 
265     theDrawer->SetDeviationCoefficient(1.e-4);
266 }
267
268 Quantity_Color color(const std::string& theSection,
269                      const std::string& theName,
270                      const std::string& theDefault)
271 {
272   std::vector<int> aColor = Config_PropManager::color(theSection, theName, theDefault);
273   return Quantity_Color(aColor[0] / 255., aColor[1] / 255., aColor[2] / 255., Quantity_TOC_RGB);
274 }
275
276 ObjectPtr getObject(const AttributePtr& theAttribute)
277 {
278   ObjectPtr anObject;
279   std::string anAttrType = theAttribute->attributeType();
280   if (anAttrType == ModelAPI_AttributeRefAttr::typeId()) {
281     AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
282     if (anAttr != NULL && anAttr->isObject())
283       anObject = anAttr->object();
284   }
285   if (anAttrType == ModelAPI_AttributeSelection::typeId()) {
286     AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
287     if (anAttr != NULL)
288       anObject = anAttr->context();
289   }
290   if (anAttrType == ModelAPI_AttributeReference::typeId()) {
291     AttributeReferencePtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(theAttribute);
292     if (anAttr.get() != NULL)
293       anObject = anAttr->value();
294   }
295   return anObject;
296 }
297
298 TopAbs_ShapeEnum getCompoundSubType(const TopoDS_Shape& theShape)
299 {
300   TopAbs_ShapeEnum aShapeType = theShape.ShapeType();
301
302   // for compounds check sub-shapes: it may be compound of needed type:
303   // Booleans may produce compounds of Solids
304   if (aShapeType == TopAbs_COMPOUND) {
305     for(TopoDS_Iterator aSubs(theShape); aSubs.More(); aSubs.Next()) {
306       if (!aSubs.Value().IsNull()) {
307         TopAbs_ShapeEnum aSubType = aSubs.Value().ShapeType();
308         if (aSubType == TopAbs_COMPOUND) { // compound of compound(s)
309           aShapeType = TopAbs_COMPOUND;
310           break;
311         }
312         if (aShapeType == TopAbs_COMPOUND) {
313           aShapeType = aSubType;
314         } else if (aShapeType != aSubType) { // compound of shapes of different types
315           aShapeType = TopAbs_COMPOUND;
316           break;
317         }
318       }
319     }
320   }
321   return aShapeType;
322 }
323
324 } // namespace ModuleBase_Tools
325
326