Repository: FreeCAD/FreeCAD
File: src/Mod/Sketcher/Gui/EditModeConstraintCoinManager.cpp (C++)

Code before:
            else {
                thisIcon.label = QString::fromUtf8(constraint->Name.c_str());
            }
        }

        iconQueue.push_back(thisIcon);
    }

    combineConstraintIcons(iconQueue);
}

void EditModeConstraintCoinManager::combineConstraintIcons(IconQueue iconQueue)
{
    // getScaleFactor gives us a ratio of pixels per some kind of real units
    float scale = ViewProviderSketchCoinAttorney::getScaleFactor(viewProvider);
    float maxDistSquared = pow(scale, 2);

    // There's room for optimisation here; we could reuse the combined icons...
    combinedConstrBoxes.clear();

    // Grid size needs to be slightly larger than the max merge distance to ensure
    // we catch neighbors.
    float gridSize = std::abs(scale) * 1.1f;
    if (gridSize < 1.0f) {
        gridSize = 1.0f;
    }

    // 2. FILTERING & PREPARATION
    // We create a list of valid indices.
    std::vector<int> validIndices;
    validIndices.reserve(iconQueue.size());

    for (size_t i = 0; i < iconQueue.size(); ++i) {
        if (!iconQueue[i].visible) {
            clearCoinImage(iconQueue[i].destination);
            continue;
        }

        // Symmetric constraints render alone (original logic)
        if (iconQueue[i].type == QStringLiteral("Constraint_Symmetric")) {
            drawTypicalConstraintIcon(iconQueue[i]);
            continue;
        }

        validIndices.push_back(static_cast<int>(i));
    }

    // 3. SPATIAL HASHING (The Grid)
    // Map: Pair(GridX, GridY) -> List of indices in iconQueue
    std::map<std::pair<int, int>, std::vector<int>> grid;


Review comment (suggestion):
```suggestion
    float gridSize = std::max(1.0f, std::abs(scale) * 1.1f);
```

Code after:
            else {
                thisIcon.label = QString::fromUtf8(constraint->Name.c_str());
            }
        }

        iconQueue.push_back(thisIcon);
    }

    combineConstraintIcons(iconQueue);
}

void EditModeConstraintCoinManager::combineConstraintIcons(IconQueue iconQueue)
{
    // getScaleFactor gives us a ratio of pixels per some kind of real units
    float scale = ViewProviderSketchCoinAttorney::getScaleFactor(viewProvider);
    float maxDistSquared = pow(scale, 2);

    // There's room for optimisation here; we could reuse the combined icons...
    combinedConstrBoxes.clear();

    // Grid size needs to be slightly larger than the max merge distance to ensure
    // we catch neighbors.
    float gridSize = std::max(1.0f, std::abs(scale) * 1.1f);

    // 2. FILTERING & PREPARATION
    // We create a list of valid indices.
    std::vector<int> validIndices;
    validIndices.reserve(iconQueue.size());

    for (size_t i = 0; i < iconQueue.size(); ++i) {
        if (!iconQueue[i].visible) {
            clearCoinImage(iconQueue[i].destination);
            continue;
        }

        // Symmetric constraints render alone (original logic)
        if (iconQueue[i].type == QStringLiteral("Constraint_Symmetric")) {
            drawTypicalConstraintIcon(iconQueue[i]);
            continue;
        }

        validIndices.push_back(static_cast<int>(i));
    }

    // 3. SPATIAL HASHING (The Grid)
    // Map: Pair(GridX, GridY) -> List of indices in iconQueue
    std::map<std::pair<int, int>, std::vector<int>> grid;

    for (int idx : validIndices) {
        const auto& icon = iconQueue[idx];
        int gx = static_cast<int>(std::floor(icon.position[0] / gridSize));