| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "rs_grid.h" |
|
|
| #include "lc_graphicviewport.h" |
| #include "lc_gridsystem.h" |
| #include "lc_isometricgrid.h" |
| #include "lc_orthogonalgrid.h" |
| #include "rs_graphic.h" |
| #include "rs_math.h" |
| #include "rs_settings.h" |
| #include "rs_units.h" |
|
|
| #ifdef EMU_C99 |
| #include "emu_c99.h" |
| #endif |
|
|
| class RS_Graphic; |
|
|
| namespace { |
|
|
| constexpr int MINIMAL_GRID_UI_STEP = 2; |
|
|
| |
| const int maxGridPoints=1000000; |
| |
| const double minimumGridWidth=1.0e-8; |
| } |
|
|
| |
| |
| |
| RS_Grid::RS_Grid(LC_GraphicViewport* graphicView) |
| :m_viewport(graphicView) |
| { |
| } |
|
|
| |
| |
| |
| |
| |
| RS_Vector RS_Grid::snapGrid(const RS_Vector& coord) const { |
| return gridSystem->snapGrid(coord); |
| } |
|
|
| void RS_Grid::loadSettings(){ |
|
|
| LC_GROUP("Appearance"); |
| m_scaleGrid = LC_GET_BOOL("ScaleGrid", true); |
| |
| auto graphic = m_viewport->getGraphic(); |
| if (graphic != nullptr) { |
| m_isometric = graphic->isIsometricGrid(); |
| isoViewType = graphic->getIsoView(); |
| m_userGrid = graphic->getVariableVector("$GRIDUNIT", RS_Vector(-1.0, -1.0)); |
| }else { |
| m_isometric = LC_GET_ONE_BOOL("Defaults", "IsometricGrid"); |
| isoViewType=static_cast<RS2::IsoGridViewType>(LC_GET_ONE_INT("Defaults", "IsoGridView", 0)); |
| m_userGrid.x = LC_GET_STR("GridSpacingX", QString("-1")).toDouble(); |
| m_userGrid.y = LC_GET_STR("GridSpacingY", QString("-1")).toDouble(); |
| } |
|
|
| bool drawMetaGrid = LC_GET_BOOL("metaGridDraw", true); |
| bool drawGrid = LC_GET_BOOL("GridDraw", true); |
| bool simpleGridRendering = LC_GET_BOOL("GridRenderSimple", false); |
| m_minGridSpacing = LC_GET_INT("MinGridSpacing", 10); |
| int gridType = LC_GET_INT("GridType", 0); |
| bool linesGrid = gridType == 1; |
|
|
| RS2::LineType metagridLineType; |
| int metaGridWidthPx; |
|
|
| if (linesGrid){ |
| metagridLineType = static_cast<RS2::LineType> (LC_GET_INT("metaGridLinesLineType", RS2::SolidLine)); |
| metaGridWidthPx = LC_GET_INT("metaGridLinesLineWidth", 1); |
| } |
| else{ |
| metagridLineType = static_cast<RS2::LineType> (LC_GET_INT("metaGridPointsLineType", RS2::DotLineTiny)); |
| metaGridWidthPx = LC_GET_INT("metaGridPointsLineWidth", 1); |
| } |
|
|
| int gridWidthPx = LC_GET_INT("GridLinesLineWidth", 1); |
| RS2::LineType gridLineType = static_cast<RS2::LineType> (LC_GET_INT("GridLinesLineType", RS2::SolidLine)); |
|
|
| bool disableGridOnPanning = LC_GET_BOOL("GridDisableWithinPan", false); |
| bool drawIsoVerticalForTop = LC_GET_BOOL("GridDrawIsoVerticalForTop", true); |
|
|
| m_metaGridEvery = LC_GET_INT("MetaGridEvery", 10); |
| LC_GROUP_END(); |
|
|
| LC_GROUP("Colors"); |
| RS_Color metaGridColor; |
| RS_Color gridColorLines = QColor(LC_GET_STR("gridLines", RS_Settings::color_meta_grid_lines)); |
| RS_Color gridColorPoint = QColor(LC_GET_STR("grid", RS_Settings::color_meta_grid_points)); |
| if (linesGrid) { |
| metaGridColor= QColor(LC_GET_STR("meta_grid_lines", RS_Settings::color_meta_grid_lines)); |
| } |
| else{ |
| metaGridColor= QColor(LC_GET_STR("meta_grid", RS_Settings::color_meta_grid_points)); |
| } |
| LC_GROUP_END(); |
|
|
| auto* gridOptions = new LC_GridSystem::LC_GridOptions(); |
| gridOptions->drawMetaGrid = drawMetaGrid; |
| gridOptions->simpleGridRendering = simpleGridRendering; |
| gridOptions->gridWidthPx = gridWidthPx; |
| gridOptions->gridLineType = gridLineType; |
| gridOptions->drawGrid = drawGrid; |
| gridOptions->drawLines = linesGrid; |
| gridOptions->gridColorPoint = gridColorPoint; |
| gridOptions->gridColorLine = gridColorLines; |
| gridOptions->metaGridLineWidthPx = metaGridWidthPx; |
| gridOptions->metaGridLineType = metagridLineType; |
| gridOptions->metaGridColor = metaGridColor; |
| gridOptions->disableGridOnPanning = disableGridOnPanning; |
| gridOptions->drawIsometricVerticalsAlways = drawIsoVerticalForTop; |
|
|
| delete gridSystem; |
|
|
| if (m_isometric){ |
| gridSystem = new LC_IsometricGrid(gridOptions, isoViewType); |
| } |
| else{ |
| gridSystem = new LC_OrthogonalGrid(gridOptions); |
| } |
| } |
|
|
| void RS_Grid::calculateSnapSettings(){ |
| if (gridSystem->isValid() || gridSystem->isGridDisabledByPanning(m_viewport)){ |
| return; |
| } |
| RS_Vector viewZero; |
| RS_Vector viewSize; |
| RS_Vector metaGridWidthToUse; |
| RS_Vector gridWidthToUse; |
| prepareGridCalculations(viewZero, viewSize,metaGridWidthToUse, gridWidthToUse); |
| gridSystem->calculateSnapInfo(viewZero, viewSize,metaGridWidthToUse, gridWidthToUse); |
| m_gridWidth = gridWidthToUse; |
| } |
|
|
| |
| |
| |
| void RS_Grid::calculateGrid() { |
| if (gridSystem->isValid() || gridSystem->isGridDisabledByPanning(m_viewport)){ |
| return; |
| } |
|
|
| RS_Vector viewZero; |
| RS_Vector viewSize; |
| RS_Vector metaGridWidthToUse; |
| RS_Vector gridWidthToUse; |
| prepareGridCalculations(viewZero, viewSize,metaGridWidthToUse, gridWidthToUse); |
|
|
| gridSystem->createGrid(m_viewport, viewZero, viewSize, metaGridWidthToUse, gridWidthToUse); |
| m_gridWidth = gridWidthToUse; |
| } |
|
|
| void RS_Grid::prepareGridCalculations(RS_Vector& viewZero,RS_Vector& viewSize,RS_Vector& metaGridWidthToUse,RS_Vector& gridWidthToUse){ |
| RS_Vector gridWidth = prepareGridWidth(); |
|
|
| gridWidthToUse = gridWidth; |
| metaGridWidthToUse = m_metaGridWidth; |
| gridWidthToUse.valid = true; |
| metaGridWidthToUse.valid = true; |
| |
| |
| |
|
|
| bool hasInfiniteAxis = false; |
| bool undefinedXSize = m_userGrid.x != 0; |
| bool undefinedYSize = m_userGrid.y != 0; |
|
|
| hasInfiniteAxis = undefinedYSize != undefinedXSize; |
|
|
| QString gridInfoStr; |
| QString metaGridInfoStr; |
| bool squareGrid = gridWidth.x == gridWidth.y; |
| if (!(gridWidth.x>minimumGridWidth && gridWidth.y>minimumGridWidth)){ |
| gridWidthToUse.valid = false; |
| metaGridWidthToUse.valid = false; |
| } |
| else { |
| double gridWidthGUIX = m_viewport->toGuiDX(gridWidth.x); |
| double gridWidthGUIY = m_viewport->toGuiDY(gridWidth.y); |
| if (gridWidthGUIX < m_minGridSpacing || gridWidthGUIY < m_minGridSpacing){ |
| gridWidthToUse.valid = false; |
| } |
| else{ |
| if (hasInfiniteAxis){ |
| gridInfoStr = QString("%1").arg(undefinedXSize ? gridWidth.y : gridWidth.x); |
| } |
| else { |
| gridInfoStr = squareGrid ? QString("%1").arg(gridWidth.x) : QString("%1 x %2").arg(gridWidth.x).arg(gridWidth.y); |
| } |
| } |
|
|
| double metaGridWidthGUIX = m_viewport->toGuiDX(m_metaGridWidth.x); |
| double metaGridWidthGUIY = m_viewport->toGuiDY(m_metaGridWidth.y); |
|
|
| if (metaGridWidthGUIX < m_minGridSpacing || metaGridWidthGUIY < m_minGridSpacing){ |
| metaGridWidthToUse.valid = false; |
| } |
| else{ |
| if (hasInfiniteAxis){ |
| metaGridInfoStr = QString("%1").arg(undefinedXSize ? m_metaGridWidth.y : m_metaGridWidth.x); |
| } |
| else { |
| metaGridInfoStr = squareGrid ? QString("%1").arg(m_metaGridWidth.x) : QString("%1 x %2").arg(m_metaGridWidth.x).arg(m_metaGridWidth.y); |
| } |
| } |
| } |
|
|
| |
| |
|
|
| viewZero = m_viewport->toUCSFromGui(0, 0); |
| viewSize = m_viewport->toUCSFromGui(m_viewport->getWidth(), m_viewport->getHeight()); |
|
|
| |
| m_gridInfoString = ""; |
| if (gridWidthToUse.valid){ |
| if (metaGridWidthToUse.valid){ |
| m_gridInfoString = QString("%1 / %2").arg(gridInfoStr).arg(metaGridInfoStr); |
| } |
| else{ |
| m_gridInfoString = QString("%1").arg(gridInfoStr); |
| } |
| } |
| else{ |
| if (metaGridWidthToUse.valid){ |
| m_gridInfoString = QString("%1").arg(metaGridInfoStr); |
| } |
| } |
|
|
| gridSystem->setGridInfiniteState(hasInfiniteAxis, undefinedXSize); |
| } |
|
|
| RS_Vector RS_Grid::prepareGridWidth() { |
|
|
| RS_Graphic* graphic = m_viewport->getGraphic(); |
|
|
| RS2::Unit unit = RS2::None; |
| RS2::LinearFormat format = RS2::Decimal; |
| if (graphic != nullptr) { |
| unit = graphic->getUnit(); |
| format = graphic->getLinearFormat(); |
| } |
|
|
| RS_Vector gridWidth; |
| |
| |
| if (RS_Units::isMetric(unit) || unit==RS2::None || |
| format==RS2::Decimal || format==RS2::Engineering) { |
| |
| gridWidth = getMetricGridWidth(m_userGrid, m_scaleGrid, m_minGridSpacing); |
|
|
| }else { |
| |
| gridWidth = getImperialGridWidth(m_userGrid, m_scaleGrid, m_minGridSpacing); |
| } |
| return gridWidth; |
| } |
|
|
|
|
| RS_Vector RS_Grid::getMetricGridWidth(RS_Vector const &userGrid, bool scaleGrid, int minGridSpacing) { |
| RS_Vector gridWidth; |
|
|
| bool hasExplicitUserGrid = false; |
|
|
| if (userGrid.x > 0.0) { |
| gridWidth.x = userGrid.x; |
| hasExplicitUserGrid = true; |
| } else { |
| gridWidth.x = minimumGridWidth; |
| } |
|
|
| if (userGrid.y > 0.0) { |
| gridWidth.y = userGrid.y; |
| hasExplicitUserGrid = true; |
| } else { |
| gridWidth.y = minimumGridWidth; |
| } |
| |
|
|
| if (scaleGrid){ |
| double guiGridWithX = m_viewport->toGuiDX(gridWidth.x); |
| double guiGridWithY = m_viewport->toGuiDY(gridWidth.y); |
| bool gridSmallerThanMin = guiGridWithX < minGridSpacing || guiGridWithY < minGridSpacing; |
| if (gridSmallerThanMin) { |
| do{ |
| gridWidth *= 10; |
| guiGridWithX = m_viewport->toGuiDX(gridWidth.x); |
| guiGridWithY = m_viewport->toGuiDY(gridWidth.y); |
| } |
| while (guiGridWithX < minGridSpacing || guiGridWithY < minGridSpacing); |
| } |
| else if (hasExplicitUserGrid){ |
| |
|
|
| RS_Vector decreasingWidth = gridWidth; |
| RS_Vector previousWidth = decreasingWidth; |
| while (true) { |
| decreasingWidth /= 10; |
|
|
| double guiGridWithX = m_viewport->toGuiDX(decreasingWidth.x); |
| double guiGridWithY = m_viewport->toGuiDY(decreasingWidth.y); |
| if (guiGridWithX < minGridSpacing || guiGridWithY < minGridSpacing){ |
| gridWidth = previousWidth; |
| break; |
| } |
| else{ |
| previousWidth = decreasingWidth; |
| } |
| } |
| } |
| } |
|
|
| |
| int metaGridStep = m_metaGridEvery; |
| m_metaGridWidth.x = gridWidth.x * metaGridStep; |
| m_metaGridWidth.y = gridWidth.y * metaGridStep; |
|
|
| |
| return gridWidth; |
| } |
|
|
| RS_Vector RS_Grid::getImperialGridWidth(RS_Vector const &userGrid, bool scaleGrid, int minGridSpacing) { |
| RS_Vector gridWidth{}; |
| |
| if (userGrid.x > 0.0) { |
| gridWidth.x = userGrid.x; |
| } else { |
| gridWidth.x = 1.0 / 1024.0; |
| } |
|
|
| if (userGrid.y > 0.0) { |
| gridWidth.y = userGrid.y; |
| } else { |
| gridWidth.y = 1.0 / 1024.0; |
| } |
| |
|
|
| RS2::Unit unit = RS2::None; |
| RS_Graphic *graphic = m_viewport->getGraphic(); |
|
|
| if (graphic) { |
| unit = graphic->getUnit(); |
| } |
|
|
| if (unit == RS2::Inch) { |
| |
|
|
| |
| |
|
|
| double guiGridWithX = m_viewport->toGuiDX(gridWidth.x); |
| double guiGridWithY = m_viewport->toGuiDY(gridWidth.y); |
| bool gridSmallerThanMin = guiGridWithX < minGridSpacing || guiGridWithY < minGridSpacing; |
| if (scaleGrid || gridSmallerThanMin) { |
| do{ |
| if (RS_Math::round(gridWidth.x) >= 36) { |
| gridWidth *= 2; |
| } else if (RS_Math::round(gridWidth.x) >= 12) { |
| gridWidth *= 3; |
| } else if (RS_Math::round(gridWidth.x) >= 4) { |
| gridWidth *= 3; |
| } else if (RS_Math::round(gridWidth.x) >= 1) { |
| gridWidth *= 2; |
| } else { |
| gridWidth *= 2; |
| } |
| guiGridWithX = m_viewport->toGuiDX(gridWidth.x); |
| guiGridWithY = m_viewport->toGuiDY(gridWidth.y); |
| } |
| while (guiGridWithX < minGridSpacing || guiGridWithY < minGridSpacing); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
|
|
| |
| m_metaGridWidth.x = 1.0; |
|
|
| int minGridSpacingX2 = minGridSpacing * 2; |
| if (m_viewport->toGuiDX(m_metaGridWidth.x) < minGridSpacingX2) { |
| |
| m_metaGridWidth.x = 12.0; |
|
|
| |
| if (m_viewport->toGuiDX(m_metaGridWidth.x) < minGridSpacingX2) { |
| m_metaGridWidth.x = 36.0; |
|
|
| |
| |
| |
| |
|
|
| |
| if (m_viewport->toGuiDX(m_metaGridWidth.x) < minGridSpacingX2) { |
| m_metaGridWidth.x = -1.0; |
| } |
|
|
| } |
| } |
|
|
| |
|
|
| |
| m_metaGridWidth.y = 1.0; |
|
|
| if (m_viewport->toGuiDY(m_metaGridWidth.y) < minGridSpacingX2) { |
| |
| m_metaGridWidth.y = 12.0; |
|
|
| |
| if (m_viewport->toGuiDY(m_metaGridWidth.y) < minGridSpacingX2) { |
| m_metaGridWidth.y = 36.0; |
|
|
| |
| |
| |
| |
|
|
| |
| if (m_viewport->toGuiDY(m_metaGridWidth.y) < minGridSpacingX2) { |
| m_metaGridWidth.y = -1.0; |
| } |
| } |
| } |
| |
| } else { |
| |
| if (scaleGrid) { |
| while (m_viewport->toGuiDX(gridWidth.x) < minGridSpacing) { |
| gridWidth.x *= 2; |
| } |
| m_metaGridWidth.x = -1.0; |
|
|
| while (m_viewport->toGuiDY(gridWidth.y) < minGridSpacing) { |
| gridWidth.y *= 2; |
| } |
| m_metaGridWidth.y = -1.0; |
| } |
| |
| } |
| |
| |
| return gridWidth; |
| } |
|
|
|
|
| QString RS_Grid::getInfo() const { |
| return m_gridInfoString; |
| } |
|
|
| bool RS_Grid::isIsometric() const { |
| return m_isometric; |
| } |
|
|
| void RS_Grid::setIsometric(bool b) { |
| m_isometric = b; |
| } |
|
|
| RS_Vector RS_Grid::getGridWidth() const { |
| return m_gridWidth; |
| } |
|
|
| RS_Vector RS_Grid::getMetaGridWidth() const { |
| return m_metaGridWidth; |
| } |
|
|
| RS_Vector const &RS_Grid::getCellVector() const { |
| return gridSystem->getCellVector(); |
| } |
|
|
| void RS_Grid::setIsoViewType(RS2::IsoGridViewType chType) { |
| isoViewType = chType; |
| } |
|
|
| RS2::IsoGridViewType RS_Grid::getIsoViewType() const { |
| return isoViewType; |
| } |
|
|
|
|
| void RS_Grid::drawGrid(RS_Painter *painter) { |
| gridSystem->draw(painter, m_viewport); |
| } |
|
|
| void RS_Grid::invalidate(bool gridOn) { |
| if (gridSystem != nullptr) { |
| gridSystem->invalidate(); |
| if (gridOn) { |
| calculateGrid(); |
| } |
| else{ |
| calculateSnapSettings(); |
| } |
| } |
| } |
|
|