diff --git a/lib/arraystats/class.c b/lib/arraystats/class.c index 58a4893a212..235de1fa6ff 100644 --- a/lib/arraystats/class.c +++ b/lib/arraystats/class.c @@ -27,6 +27,9 @@ double AS_class_apply_algorithm(int algo, const double data[], int nrec, { double finfo = 0.0; + if (nrec < 1) + G_fatal_error(_("Cannot classify an empty set of values")); + switch (algo) { case CLASS_INTERVAL: finfo = AS_class_interval(data, nrec, *nbreaks, classbreaks); diff --git a/vector/v.class/main.c b/vector/v.class/main.c index 0963b0394cf..324c9481456 100644 --- a/vector/v.class/main.c +++ b/vector/v.class/main.c @@ -38,9 +38,9 @@ int main(int argc, char *argv[]) int ofield; int nrec, ctype, nbclass, nbreaks, *frequencies; int ret, i; - double finfo; + double finfo = 0; double *classbreaks, min, max, *data; - struct GASTATS stats; + struct GASTATS stats = {0}; char *desc, *fs; enum OutputFormat format; G_JSON_Value *root_value = NULL, *intervals_value = NULL, @@ -174,6 +174,9 @@ int main(int argc, char *argv[]) if (nrec < 0) G_fatal_error(_("Unable to select data from table")); + if (nrec == 0) + G_warning(_("No records selected from table <%s>"), Fi->table); + db_close_database_shutdown_driver(Driver); ret = db_CatValArray_sort_by_value(&Cvarr); @@ -203,15 +206,19 @@ int main(int argc, char *argv[]) /* Get classbreaks for given algorithm and number of classbreaks. * finfo takes any info coming from the classification algorithms - * equ algorithm can alter number of class breaks */ - finfo = AS_class_apply_algorithm(AS_option_to_algorithm(algo_opt), data, - nrec, &nbreaks, classbreaks); - - if (G_strcasecmp(algo_opt->answer, "dis") == 0 && finfo < 3.84148) - G_warning( - _("The discontinuities algorithm indicates that some " - "class breaks are not statistically significant at " - "alpha=0.05. You are advised to reduce the number of classes.")); + * equ algorithm can alter number of class breaks. + * With no data there is nothing to classify and the class breaks stay + * at zero. */ + if (nrec > 0) { + finfo = AS_class_apply_algorithm(AS_option_to_algorithm(algo_opt), data, + nrec, &nbreaks, classbreaks); + + if (G_strcasecmp(algo_opt->answer, "dis") == 0 && finfo < 3.84148) + G_warning(_("The discontinuities algorithm indicates that some " + "class breaks are not statistically significant at " + "alpha=0.05. You are advised to reduce the number of " + "classes.")); + } /*output to be piped to other modules ? */ if (breaks_flag->answer) { @@ -280,12 +287,15 @@ int main(int argc, char *argv[]) for (i = 0; i < nbreaks + 1; i++) frequencies[i] = 0; - ret = - AS_class_frequencies(data, nrec, nbreaks, classbreaks, frequencies); - AS_basic_stats(data, nrec, &stats); + min = max = 0; + if (nrec > 0) { + ret = AS_class_frequencies(data, nrec, nbreaks, classbreaks, + frequencies); + AS_basic_stats(data, nrec, &stats); - min = data[0]; - max = data[nrec - 1]; + min = data[0]; + max = data[nrec - 1]; + } /* as equ algorithm can modify number of breaks we recalculate number of * classes diff --git a/vector/v.class/tests/test_v_class.py b/vector/v.class/tests/test_v_class.py index c54f7e0894c..e38d39ca51d 100644 --- a/vector/v.class/tests/test_v_class.py +++ b/vector/v.class/tests/test_v_class.py @@ -286,11 +286,11 @@ def test_v_class_where_no_matches(setup_vector_with_values): where="value > 100", # No points satisfy this algorithm="int", nbclasses=5, - flags="g", + flags="b", env=session.env, ) - breaks = [float(b) for b in output.strip().split(",")] if output.strip() else [] - assert len(breaks) == 4 # For 5 classes → 4 breaks + breaks = [float(b) for b in output.strip().split(",")] + assert len(breaks) == 4 # For 5 classes, there are 4 breaks assert all(b == 0.0 for b in breaks)