diff --git a/src/components/MapRenderer/WaffleMapRenderer.tsx b/src/components/MapRenderer/WaffleMapRenderer.tsx index fe4a1da1..a85ae024 100644 --- a/src/components/MapRenderer/WaffleMapRenderer.tsx +++ b/src/components/MapRenderer/WaffleMapRenderer.tsx @@ -8,7 +8,7 @@ import { // Helpers import { bindDragBehavior, mergeFilterIds } from './common.tsx'; -import { Mfloor, Mround } from '../../helpers/math'; +import { Mfloor, Mround, Msqrt } from '../../helpers/math'; // Directives import bindData from '../../directives/bind-data'; @@ -54,7 +54,6 @@ export default function waffleRenderer( mgt:symbol-type={params.symbolType} mgt:size={params.size} mgt:anchor={params.anchor} - mgt:columns={params.columns} mgt:spacing={params.spacing} > @@ -70,21 +69,25 @@ export default function waffleRenderer( count: Mround(+feature.properties[variable.name] / params.symbolValue), })); + const columns = params.columns.type === 'fixed' + ? params.columns.value + : Mround(Msqrt(variableSymbols.reduce((acc, variable) => acc + variable.count, 0))); + // Central position of the symbol block let offsetCentroidX = 0; // value for anchor = 'start' if (params.symbolType === 'circle') { if (params.anchor === 'middle') { offsetCentroidX = (params.size + params.spacing) - * (params.columns / 2) - (params.size * 0.5); + * (columns / 2) - (params.size * 0.5); } else if (params.anchor === 'end') { - offsetCentroidX = (params.size + params.spacing) * params.columns - params.size; + offsetCentroidX = (params.size + params.spacing) * columns - params.size; } } else { // eslint-disable-next-line no-lonely-if if (params.anchor === 'middle') { - offsetCentroidX = (params.size + params.spacing) * (params.columns / 2); + offsetCentroidX = (params.size + params.spacing) * (columns / 2); } else if (params.anchor === 'end') { - offsetCentroidX = (params.size + params.spacing) * params.columns; + offsetCentroidX = (params.size + params.spacing) * columns; } } @@ -93,15 +96,16 @@ export default function waffleRenderer( return {(variable) => {(_, i) => { const tx = Mround( - (symbolIndex % params.columns) * (params.size + params.spacing), + (symbolIndex % columns) * (params.size + params.spacing), ); const ty = Mfloor( - Mfloor(symbolIndex / params.columns) * (params.size + params.spacing), + Mfloor(symbolIndex / columns) * (params.size + params.spacing), ); symbolIndex += 1; // Increment for next position return params.symbolType === 'circle' ? ( diff --git a/src/components/PortrayalOption/WaffleSettings.tsx b/src/components/PortrayalOption/WaffleSettings.tsx index 87e0d3e0..8a26ae28 100644 --- a/src/components/PortrayalOption/WaffleSettings.tsx +++ b/src/components/PortrayalOption/WaffleSettings.tsx @@ -81,6 +81,10 @@ function guessSymbolValue( minSum = Mmin(minSum, sum); }); + if (maxSum < 45) { + return 1; + } + // We want to find a divisor (ideally a multiple of 10) that // allows the user to encode the sum of the selected variables // in a stack of symbols (without having too much symbols for the @@ -137,7 +141,7 @@ function onClickValidate( symbolValue: number, symbolValueSentence: string, size: number, - columns: number, + columns: { type: 'dynamic' } | { type: 'fixed', value: number }, spacing: number, symbolType: ProportionalSymbolsSymbolType.circle | ProportionalSymbolsSymbolType.square, newLayerName: string, @@ -302,6 +306,11 @@ export default function WaffleSettings( setSymbolSize, ] = createSignal(10); + const [ + columnsType, + setColumnsType, + ] = createSignal<'dynamic' | 'fixed'>('fixed'); + // Number of columns const [ columns, @@ -349,6 +358,10 @@ export default function WaffleSettings( await yieldOrContinue('smooth'); + const ct = columnsType() === 'fixed' + ? { type: 'fixed', value: columns() } + : { type: 'dynamic' }; + // Actually create the portrayal setTimeout(() => { onClickValidate( @@ -357,7 +370,7 @@ export default function WaffleSettings( symbolValue(), LL().FunctionalitiesSection.WaffleOptions.SymbolRatioNote({ value: symbolValue() }), symbolSize(), - columns(), + ct, space(), symbolType(), layerName, @@ -423,14 +436,28 @@ export default function WaffleSettings( max={30} step={1} /> - { setColumns(value); }} - min={1} - max={30} - step={1} - /> + { setColumnsType(value as 'dynamic' | 'fixed'); }} + > + + + + + { setColumns(value); }} + min={1} + max={30} + step={1} + /> + { } else if (typePortrayal === 'waffle') { const symbolType = g.getAttribute('mgt:symbol-type')!; const size = +g.getAttribute('mgt:size')!; - const columns = +g.getAttribute('mgt:columns')!; const spacing = +g.getAttribute('mgt:spacing')!; const anchor = g.getAttribute('mgt:anchor')!; g.querySelectorAll('g').forEach((gg) => { + const columns = +gg.getAttribute('mgt:columns')!; const coords = globalStore.pathGenerator.centroid( // eslint-disable-next-line no-underscore-dangle (gg as SVGGElement & ID3Element).__data__.geometry, diff --git a/src/i18n/en/index.ts b/src/i18n/en/index.ts index 778c186c..b6514dcc 100644 --- a/src/i18n/en/index.ts +++ b/src/i18n/en/index.ts @@ -1100,7 +1100,10 @@ const en = { Variables: 'Variables (two or more)', SymbolType: 'Symbol type', Spacing: 'Spacing', - Columns: 'Number of columns', + ColumnsType: 'Columns type', + ColumnsDynamic: 'Dynamic', + ColumnsFixed: 'Fixed', + ColumnsNumber: 'Number of columns', SymbolSize: 'Symbol size', SymbolValue: 'Value expressed by each symbol', NewLayerName: 'Waffle_{layerName}', diff --git a/src/i18n/fr/index.ts b/src/i18n/fr/index.ts index 8189e19d..beed4f49 100644 --- a/src/i18n/fr/index.ts +++ b/src/i18n/fr/index.ts @@ -1100,7 +1100,10 @@ const fr = { Variables: 'Variables (deux ou plus)', SymbolType: 'Type de symbole', Spacing: 'Espacement', - Columns: 'Nombre de colonnes', + ColumnsType: 'Type de colonnes', + ColumnsDynamic: 'Dynamique', + ColumnsFixed: 'Fixe', + ColumnsNumber: 'Nombre de colonnes', SymbolSize: 'Taille du symbole', SymbolValue: 'Valeur représentée par chaque symbole', NewLayerName: 'Gaufre_{layerName}', diff --git a/src/i18n/i18n-types.ts b/src/i18n/i18n-types.ts index ba4f4560..6840393f 100644 --- a/src/i18n/i18n-types.ts +++ b/src/i18n/i18n-types.ts @@ -4419,10 +4419,22 @@ type RootTranslation = { * S​p​a​c​i​n​g */ Spacing: string + /** + * C​o​l​u​m​n​s​ ​t​y​p​e + */ + ColumnsType: string + /** + * D​y​n​a​m​i​c + */ + ColumnsDynamic: string + /** + * F​i​x​e​d + */ + ColumnsFixed: string /** * N​u​m​b​e​r​ ​o​f​ ​c​o​l​u​m​n​s */ - Columns: string + ColumnsNumber: string /** * S​y​m​b​o​l​ ​s​i​z​e */ @@ -10291,10 +10303,22 @@ export type TranslationFunctions = { * Spacing */ Spacing: () => LocalizedString + /** + * Columns type + */ + ColumnsType: () => LocalizedString + /** + * Dynamic + */ + ColumnsDynamic: () => LocalizedString + /** + * Fixed + */ + ColumnsFixed: () => LocalizedString /** * Number of columns */ - Columns: () => LocalizedString + ColumnsNumber: () => LocalizedString /** * Symbol size */