214 if (!checkAndCalculateBounds()) {
216 sumSquaredDifferences = std::numeric_limits<T>::quiet_NaN();
221 const auto &gridTarget = levelSetTarget->getGrid();
222 double gridDelta = gridTarget.getGridDelta();
225 viennahrle::ConstDenseCellIterator<typename Domain<T, D>::DomainType>
226 itSample(levelSetSample->getDomain(), minIndex);
227 viennahrle::ConstDenseCellIterator<typename Domain<T, D>::DomainType>
228 itTarget(levelSetTarget->getDomain(), minIndex);
230 sumSquaredDifferences = 0.0;
234 std::unordered_map<viennahrle::Index<D>, size_t,
235 typename viennahrle::Index<D>::hash>
237 std::vector<T> differenceValues;
238 size_t currentPointId = 0;
240 const bool generateMesh = outputMesh !=
nullptr;
245 for (
unsigned i = 0; i < 3; ++i) {
246 outputMesh->minimumExtent[i] =
247 (i < D) ? std::numeric_limits<T>::max() : 0.0;
248 outputMesh->maximumExtent[i] =
249 (i < D) ? std::numeric_limits<T>::lowest() : 0.0;
254 for (; itSample.getIndices() < maxIndex; itSample.next()) {
256 T xCoord = itSample.getIndices()[0] * gridDelta;
257 T yCoord = (
D > 1) ? itSample.getIndices()[1] * gridDelta : 0;
258 T zCoord = (
D > 2) ? itSample.getIndices()[2] * gridDelta : 0;
261 if (useXRange && (xCoord < xRangeMin || xCoord > xRangeMax)) {
266 if (
D > 1 && useYRange && (yCoord < yRangeMin || yCoord > yRangeMax)) {
271 if (
D > 2 && useZRange && (zCoord < zRangeMin || zCoord > zRangeMax)) {
276 itTarget.goToIndicesSequential(itSample.getIndices());
283 for (
int i = 0; i < (1 <<
D); ++i) {
284 valueSample += itSample.getCorner(i).getValue();
285 valueTarget += itTarget.getCorner(i).getValue();
287 valueTarget /= (1 <<
D);
288 valueSample /= (1 <<
D);
291 if (std::isinf(valueTarget) || std::isinf(valueSample) ||
292 std::abs(valueTarget) > 1000 || std::abs(valueSample) > 1000) {
297 T diff = std::abs(valueTarget - valueSample) * gridDelta;
298 T diffSquared = diff * diff;
299 sumSquaredDifferences += diffSquared;
300 sumDifferences += diff;
305 std::array<unsigned, 1 << D> voxel;
306 bool addVoxel =
true;
309 for (
unsigned i = 0; i < (1 <<
D); ++i) {
310 viennahrle::Index<D> index;
311 for (
unsigned j = 0; j <
D; ++j) {
313 itSample.getIndices(j) + itSample.getCorner(i).getOffset()[j];
314 if (index[j] > maxIndex[j]) {
320 auto pointIdValue = std::make_pair(index, currentPointId);
321 auto pointIdPair = pointIdMapping.insert(pointIdValue);
322 voxel[i] = pointIdPair.first->second;
323 if (pointIdPair.second) {
332 if constexpr (
D == 3) {
333 std::array<unsigned, 8> hexa{voxel[0], voxel[1], voxel[3],
334 voxel[2], voxel[4], voxel[5],
336 outputMesh->hexas.push_back(hexa);
337 }
else if constexpr (
D == 2) {
338 std::array<unsigned, 4> quad{voxel[0], voxel[1], voxel[3],
340 outputMesh->tetras.push_back(quad);
345 differenceValues.push_back(outputMeshSquaredDifferences ? diffSquared
352 if (generateMesh && !pointIdMapping.empty()) {
353 outputMesh->nodes.resize(pointIdMapping.size());
354 for (auto it = pointIdMapping.begin(); it != pointIdMapping.end(); ++it) {
355 std::array<T, 3> coords{};
356 for (unsigned i = 0; i < D; ++i) {
357 coords[i] = gridDelta * it->first[i];
359 if (coords[i] < outputMesh->minimumExtent[i]) {
360 outputMesh->minimumExtent[i] = coords[i];
361 } else if (coords[i] > outputMesh->maximumExtent[i]) {
362 outputMesh->maximumExtent[i] = coords[i];
365 outputMesh->nodes[it->second] = coords;
368 assert(differenceValues.size() ==
369 outputMesh->template getElements<1 <<
D>().size());
370 outputMesh->cellData.insertNextScalarData(std::move(differenceValues),
371 outputMeshSquaredDifferences
372 ?
"Squared differences"
373 :
"Absolute differences");