47 for (int i : {0, 1, 2}) |
47 for (int i : {0, 1, 2}) |
48 for (int j : {0, 1, 2}) |
48 for (int j : {0, 1, 2}) |
49 { |
49 { |
50 QLayoutItem* item = this->ui.matrixLayout->itemAtPosition(i, j); |
50 QLayoutItem* item = this->ui.matrixLayout->itemAtPosition(i, j); |
51 QDoubleSpinBox* spinbox = item ? qobject_cast<QDoubleSpinBox*>(item->widget()) : nullptr; |
51 QDoubleSpinBox* spinbox = item ? qobject_cast<QDoubleSpinBox*>(item->widget()) : nullptr; |
|
52 spinbox->blockSignals(true); |
52 spinbox->setValue(reference->transformationMatrix()(i, j)); |
53 spinbox->setValue(reference->transformationMatrix()(i, j)); |
|
54 spinbox->blockSignals(false); |
|
55 connect( |
|
56 spinbox, |
|
57 qOverload<double>(&QDoubleSpinBox::valueChanged), |
|
58 this, |
|
59 &SubfileReferenceEditor::matrixChanged |
|
60 ); |
53 } |
61 } |
54 connect( |
62 connect( |
55 this->ui.primitivesTreeView, |
63 this->ui.primitivesTreeView, |
56 &QTreeView::clicked, |
64 &QTreeView::clicked, |
57 [&](const QModelIndex& index) |
65 [&](const QModelIndex& index) |
61 |
69 |
62 if (primitiveName.isValid()) |
70 if (primitiveName.isValid()) |
63 this->ui.referenceName->setText(primitiveName.toString()); |
71 this->ui.referenceName->setText(primitiveName.toString()); |
64 } |
72 } |
65 ); |
73 ); |
|
74 |
|
75 for (QDoubleSpinBox* spinbox : {this->ui.scalingX, this->ui.scalingY, this->ui.scalingZ}) |
|
76 { |
|
77 connect( |
|
78 spinbox, |
|
79 qOverload<double>(&QDoubleSpinBox::valueChanged), |
|
80 this, |
|
81 &SubfileReferenceEditor::scalingChanged |
|
82 ); |
|
83 } |
|
84 |
|
85 // Fill in the initial scaling values |
|
86 for (int column : {0, 1, 2}) |
|
87 { |
|
88 QDoubleSpinBox* spinbox = this->vectorElement(column); |
|
89 spinbox->blockSignals(true); |
|
90 spinbox->setValue(this->matrixScaling(column)); |
|
91 spinbox->blockSignals(false); |
|
92 } |
|
93 } |
|
94 |
|
95 SubfileReferenceEditor::~SubfileReferenceEditor() |
|
96 { |
|
97 delete &this->ui; |
|
98 } |
|
99 |
|
100 /* |
|
101 * Returns a spinbox from the matrix grid at position (row, column). |
|
102 * Row and column must be within [0, 2]. |
|
103 */ |
|
104 QDoubleSpinBox* SubfileReferenceEditor::matrixCell(int row, int column) const |
|
105 { |
|
106 if (qBound(0, row, 2) != row or qBound(0, column, 2) != column) |
|
107 { |
|
108 throw std::out_of_range {"bad row and column values"}; |
|
109 } |
|
110 else |
|
111 { |
|
112 QLayoutItem* item = this->ui.matrixLayout->itemAtPosition(row, column); |
|
113 return item ? qobject_cast<QDoubleSpinBox*>(item->widget()) : nullptr; |
|
114 } |
|
115 } |
|
116 |
|
117 /* |
|
118 * Returns a spinbox for the vector element at the given position |
|
119 * Index must be within [0, 2] |
|
120 */ |
|
121 QDoubleSpinBox* SubfileReferenceEditor::vectorElement(int index) |
|
122 { |
|
123 switch (index) |
|
124 { |
|
125 case 0: |
|
126 return this->ui.scalingX; |
|
127 |
|
128 case 1: |
|
129 return this->ui.scalingY; |
|
130 |
|
131 case 2: |
|
132 return this->ui.scalingZ; |
|
133 |
|
134 default: |
|
135 throw std::out_of_range {"bad index"}; |
|
136 } |
66 } |
137 } |
67 |
138 |
68 void SubfileReferenceEditor::accept() |
139 void SubfileReferenceEditor::accept() |
69 { |
140 { |
70 this->reference->setReferenceName(this->ui.referenceName->text()); |
141 this->reference->setReferenceName(this->ui.referenceName->text()); |
71 Matrix transformationMatrix; |
142 Matrix transformationMatrix; |
72 for (int i : {0, 1, 2}) |
143 for (int i : {0, 1, 2}) |
73 for (int j : {0, 1, 2}) |
144 for (int j : {0, 1, 2}) |
74 { |
145 { |
75 QLayoutItem* item = this->ui.matrixLayout->itemAtPosition(i, j); |
146 transformationMatrix(i, j) = this->matrixCell(i, j)->value(); |
76 QDoubleSpinBox* spinbox = item ? qobject_cast<QDoubleSpinBox*>(item->widget()) : nullptr; |
|
77 transformationMatrix(i, j) = spinbox->value(); |
|
78 } |
147 } |
79 this->reference->setTransformationMatrix(transformationMatrix); |
148 this->reference->setTransformationMatrix(transformationMatrix); |
80 this->reference->setPosition({ |
149 this->reference->setPosition({ |
81 this->ui.positionX->value(), |
150 this->ui.positionX->value(), |
82 this->ui.positionY->value(), |
151 this->ui.positionY->value(), |
89 void SubfileReferenceEditor::setPrimitivesTree(PrimitiveManager* primitives) |
158 void SubfileReferenceEditor::setPrimitivesTree(PrimitiveManager* primitives) |
90 { |
159 { |
91 this->ui.primitivesTreeView->setModel(primitives); |
160 this->ui.primitivesTreeView->setModel(primitives); |
92 } |
161 } |
93 |
162 |
94 SubfileReferenceEditor::~SubfileReferenceEditor() |
163 double SubfileReferenceEditor::matrixScaling(int column) const |
95 { |
164 { |
96 delete &this->ui; |
165 return sqrt( |
97 } |
166 pow(this->matrixCell(0, column)->value(), 2) + |
|
167 pow(this->matrixCell(1, column)->value(), 2) + |
|
168 pow(this->matrixCell(2, column)->value(), 2) |
|
169 ); |
|
170 } |
|
171 |
|
172 /* |
|
173 * Updates the appropriate matrix column when a scaling vector element is changed. |
|
174 */ |
|
175 void SubfileReferenceEditor::scalingChanged() |
|
176 { |
|
177 for (int column : {0, 1, 2}) |
|
178 { |
|
179 if (this->sender() == this->vectorElement(column)) |
|
180 { |
|
181 double oldScaling = this->matrixScaling(column); |
|
182 double newScaling = static_cast<QDoubleSpinBox*>(this->sender())->value(); |
|
183 |
|
184 if (not qFuzzyCompare(newScaling, 0.0)) |
|
185 { |
|
186 for (int row : {0, 1, 2}) |
|
187 { |
|
188 double cellValue = abs(this->matrixCell(row, column)->value()); |
|
189 cellValue *= newScaling / oldScaling; |
|
190 QDoubleSpinBox* cellWidget = this->matrixCell(row, column); |
|
191 cellWidget->blockSignals(true); |
|
192 cellWidget->setValue(cellValue); |
|
193 cellWidget->blockSignals(false); |
|
194 } |
|
195 } |
|
196 |
|
197 break; |
|
198 } |
|
199 } |
|
200 } |
|
201 |
|
202 /* |
|
203 * Finds the position for the given cell widget. |
|
204 */ |
|
205 QPair<int, int> SubfileReferenceEditor::cellPosition(QDoubleSpinBox* cellWidget) |
|
206 { |
|
207 for (int row : {0, 1, 2}) |
|
208 for (int column : {0, 1, 2}) |
|
209 { |
|
210 if (this->matrixCell(row, column) == cellWidget) |
|
211 return {row, column}; |
|
212 } |
|
213 |
|
214 throw std::out_of_range {"widget is not in the matrix"}; |
|
215 } |
|
216 |
|
217 /* |
|
218 * Updates the appropriate scaling vector element when a matrix cell is changed. |
|
219 */ |
|
220 void SubfileReferenceEditor::matrixChanged() |
|
221 { |
|
222 QDoubleSpinBox* cellWidget = static_cast<QDoubleSpinBox*>(this->sender()); |
|
223 |
|
224 try |
|
225 { |
|
226 int column = this->cellPosition(cellWidget).second; |
|
227 QDoubleSpinBox* spinbox = this->vectorElement(column); |
|
228 spinbox->blockSignals(true); |
|
229 spinbox->setValue(this->matrixScaling(column)); |
|
230 spinbox->blockSignals(false); |
|
231 } |
|
232 catch (const std::out_of_range&) {} |
|
233 } |