@@ -662,7 +662,8 @@ PJ *proj_create_from_database(PJ_CONTEXT *ctx, const char *auth_name,
662
662
// ---------------------------------------------------------------------------
663
663
664
664
// ! @cond Doxygen_Suppress
665
- static const char *get_unit_category (UnitOfMeasure::Type type) {
665
+ static const char *get_unit_category (const std::string &unit_name,
666
+ UnitOfMeasure::Type type) {
666
667
const char *ret = nullptr ;
667
668
switch (type) {
668
669
case UnitOfMeasure::Type::UNKNOWN:
@@ -672,19 +673,26 @@ static const char *get_unit_category(UnitOfMeasure::Type type) {
672
673
ret = " none" ;
673
674
break ;
674
675
case UnitOfMeasure::Type::ANGULAR:
675
- ret = " angular" ;
676
+ ret = unit_name.find (" per " ) != std::string::npos ? " angular_per_time"
677
+ : " angular" ;
676
678
break ;
677
679
case UnitOfMeasure::Type::LINEAR:
678
- ret = " linear" ;
680
+ ret = unit_name.find (" per " ) != std::string::npos ? " linear_per_time"
681
+ : " linear" ;
679
682
break ;
680
683
case UnitOfMeasure::Type::SCALE:
681
- ret = " scale" ;
684
+ ret = unit_name.find (" per year" ) != std::string::npos ||
685
+ unit_name.find (" per second" ) != std::string::npos
686
+ ? " scale_per_time"
687
+ : " scale" ;
682
688
break ;
683
689
case UnitOfMeasure::Type::TIME:
684
690
ret = " time" ;
685
691
break ;
686
692
case UnitOfMeasure::Type::PARAMETRIC:
687
- ret = " parametric" ;
693
+ ret = unit_name.find (" per " ) != std::string::npos
694
+ ? " parametric_per_time"
695
+ : " parametric" ;
688
696
break ;
689
697
}
690
698
return ret;
@@ -704,8 +712,9 @@ static const char *get_unit_category(UnitOfMeasure::Type type) {
704
712
* @param out_conv_factor Pointer to a value to store the conversion
705
713
* factor of the prime meridian longitude unit to radian. or NULL
706
714
* @param out_category Pointer to a string value to store the parameter name. or
707
- * NULL. This value might be "unknown", "none", "linear", "angular", "scale",
708
- * "time" or "parametric";
715
+ * NULL. This value might be "unknown", "none", "linear", "linear_per_time",
716
+ * "angular", "angular_per_time", "scale", "scale_per_time", "time",
717
+ * "parametric" or "parametric_per_time"
709
718
* @return TRUE in case of success
710
719
*/
711
720
int proj_uom_get_info_from_database (PJ_CONTEXT *ctx, const char *auth_name,
@@ -726,7 +735,7 @@ int proj_uom_get_info_from_database(PJ_CONTEXT *ctx, const char *auth_name,
726
735
*out_conv_factor = obj->conversionToSI ();
727
736
}
728
737
if (out_category) {
729
- *out_category = get_unit_category (obj->type ());
738
+ *out_category = get_unit_category (obj->name (), obj-> type ());
730
739
}
731
740
ctx->cpp_context ->autoCloseDbIfNeeded ();
732
741
return true ;
@@ -2585,6 +2594,100 @@ void proj_crs_info_list_destroy(PROJ_CRS_INFO **list) {
2585
2594
2586
2595
// ---------------------------------------------------------------------------
2587
2596
2597
+ /* * \brief Enumerate units from the database, taking into account various
2598
+ * criteria.
2599
+ *
2600
+ * The returned object is an array of PROJ_UNIT_INFO* pointers, whose last
2601
+ * entry is NULL. This array should be freed with proj_unit_list_destroy()
2602
+ *
2603
+ * @param ctx PROJ context, or NULL for default context
2604
+ * @param auth_name Authority name, used to restrict the search.
2605
+ * Or NULL for all authorities.
2606
+ * @param category Filter by category, if this parameter is not NULL. Category
2607
+ * is one of "linear", "linear_per_time", "angular", "angular_per_time",
2608
+ * "scale", "scale_per_time" or "time"
2609
+ * @param allow_deprecated whether we should return deprecated objects as well.
2610
+ * @param out_result_count Output parameter pointing to an integer to receive
2611
+ * the size of the result list. Might be NULL
2612
+ * @return an array of PROJ_UNIT_INFO* pointers to be freed with
2613
+ * proj_unit_list_destroy(), or NULL in case of error.
2614
+ *
2615
+ * @since 7.1
2616
+ */
2617
+ PROJ_UNIT_INFO **proj_get_units_from_database (PJ_CONTEXT *ctx,
2618
+ const char *auth_name,
2619
+ const char *category,
2620
+ int allow_deprecated,
2621
+ int *out_result_count) {
2622
+ SANITIZE_CTX (ctx);
2623
+ PROJ_UNIT_INFO **ret = nullptr ;
2624
+ int i = 0 ;
2625
+ try {
2626
+ auto factory = AuthorityFactory::create (getDBcontext (ctx),
2627
+ auth_name ? auth_name : " " );
2628
+ auto list = factory->getUnitList ();
2629
+ ret = new PROJ_UNIT_INFO *[list.size () + 1 ];
2630
+ for (const auto &info : list) {
2631
+ if (category && info.category != category) {
2632
+ continue ;
2633
+ }
2634
+ if (!allow_deprecated && info.deprecated ) {
2635
+ continue ;
2636
+ }
2637
+ ret[i] = new PROJ_UNIT_INFO;
2638
+ ret[i]->auth_name = pj_strdup (info.authName .c_str ());
2639
+ ret[i]->code = pj_strdup (info.code .c_str ());
2640
+ ret[i]->name = pj_strdup (info.name .c_str ());
2641
+ ret[i]->category = pj_strdup (info.category .c_str ());
2642
+ ret[i]->conv_factor = info.convFactor ;
2643
+ ret[i]->proj_short_name =
2644
+ info.projShortName .empty ()
2645
+ ? nullptr
2646
+ : pj_strdup (info.projShortName .c_str ());
2647
+ ret[i]->deprecated = info.deprecated ;
2648
+ i++;
2649
+ }
2650
+ ret[i] = nullptr ;
2651
+ if (out_result_count)
2652
+ *out_result_count = i;
2653
+ ctx->cpp_context ->autoCloseDbIfNeeded ();
2654
+ return ret;
2655
+ } catch (const std::exception &e) {
2656
+ proj_log_error (ctx, __FUNCTION__, e.what ());
2657
+ if (ret) {
2658
+ ret[i + 1 ] = nullptr ;
2659
+ proj_unit_list_destroy (ret);
2660
+ }
2661
+ if (out_result_count)
2662
+ *out_result_count = 0 ;
2663
+ }
2664
+ ctx->cpp_context ->autoCloseDbIfNeeded ();
2665
+ return nullptr ;
2666
+ }
2667
+
2668
+ // ---------------------------------------------------------------------------
2669
+
2670
+ /* * \brief Destroy the result returned by
2671
+ * proj_get_units_from_database().
2672
+ *
2673
+ * @since 7.1
2674
+ */
2675
+ void proj_unit_list_destroy (PROJ_UNIT_INFO **list) {
2676
+ if (list) {
2677
+ for (int i = 0 ; list[i] != nullptr ; i++) {
2678
+ pj_dalloc (list[i]->auth_name );
2679
+ pj_dalloc (list[i]->code );
2680
+ pj_dalloc (list[i]->name );
2681
+ pj_dalloc (list[i]->category );
2682
+ pj_dalloc (list[i]->proj_short_name );
2683
+ delete list[i];
2684
+ }
2685
+ delete[] list;
2686
+ }
2687
+ }
2688
+
2689
+ // ---------------------------------------------------------------------------
2690
+
2588
2691
/* * \brief Return the Conversion of a DerivedCRS (such as a ProjectedCRS),
2589
2692
* or the Transformation from the baseCRS to the hubCRS of a BoundCRS
2590
2693
*
@@ -6749,8 +6852,9 @@ int proj_coordoperation_get_param_index(PJ_CONTEXT *ctx,
6749
6852
* unit code. or NULL
6750
6853
* @param out_unit_category Pointer to a string value to store the parameter
6751
6854
* name. or
6752
- * NULL. This value might be "unknown", "none", "linear", "angular", "scale",
6753
- * "time" or "parametric";
6855
+ * NULL. This value might be "unknown", "none", "linear", "linear_per_time",
6856
+ * "angular", "angular_per_time", "scale", "scale_per_time", "time",
6857
+ * "parametric" or "parametric_per_time"
6754
6858
* @return TRUE in case of success.
6755
6859
*/
6756
6860
@@ -6852,7 +6956,8 @@ int proj_coordoperation_get_param(
6852
6956
*out_unit_code = unit.code ().c_str ();
6853
6957
}
6854
6958
if (out_unit_category) {
6855
- *out_unit_category = get_unit_category (unit.type ());
6959
+ *out_unit_category =
6960
+ get_unit_category (unit.name (), unit.type ());
6856
6961
}
6857
6962
}
6858
6963
}
0 commit comments