star-cpr

Clip 2D meshes with 2D polygons
git clone git://git.meso-star.fr/star-cpr.git
Log | Files | Refs | README | LICENSE

scpr_device.c (4766B)


      1 /* Copyright (C) 2016-2018, 2021-2024 |Méso|Star> (contact@meso-star.com)
      2  *
      3  * This program is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published by
      5  * the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * This program is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with this program. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "scpr.h"
     17 #include "scpr_c.h"
     18 
     19 #include <polygon.h>
     20 #include <rsys/mem_allocator.h>
     21 #include <rsys/logger.h>
     22 #include <rsys/rsys.h>
     23 #include <rsys/double2.h>
     24 
     25 #include <math.h>
     26 
     27 #ifdef OS_UNIX
     28   /* On UNIX assume a VT100-like terminal emulator */
     29   #define MSG_INFO_PREFIX "star-cpr (\x1b[1m\x1b[32minfo\x1b[0m): "
     30   #define MSG_ERROR_PREFIX "star-cpr (\x1b[1m\x1b[31merror\x1b[0m): "
     31   #define MSG_WARNING_PREFIX "star-cpr (\x1b[1m\x1b[33mwarning\x1b[0m): "
     32 #else
     33   #define MSG_INFO_PREFIX "star-cpr (info): "
     34   #define MSG_ERROR_PREFIX "star-cpr (error): "
     35   #define MSG_WARNING_PREFIX "star-cpr (warning): "
     36 #endif
     37 
     38 /*******************************************************************************
     39  * Helper functions
     40  ******************************************************************************/
     41 static void
     42 device_release(ref_T* ref)
     43 {
     44   struct scpr_device* device;
     45   struct mem_allocator* allocator;
     46   ASSERT(ref);
     47   device = CONTAINER_OF(ref, struct scpr_device, ref);
     48   allocator = device->allocator;
     49   MEM_RM(allocator, device);
     50 }
     51 
     52 int INLINE
     53 is_in_range
     54   (const double x,
     55    const double range[2])
     56 {
     57   ASSERT(range);
     58   return range[0] <= x && x <= range[1];
     59 }
     60 
     61 /*******************************************************************************
     62  * Exported functions
     63  ******************************************************************************/
     64 res_T
     65 scpr_device_create
     66   (const struct scpr_device_create_args* args,
     67    struct scpr_device** out_device)
     68 {
     69   struct scpr_device* device = NULL;
     70   struct mem_allocator* allocator = NULL;
     71   res_T res = RES_OK;
     72 
     73   if(!args || !out_device || args->precision < 0 || args->precision > 8) {
     74     res = RES_BAD_ARG;
     75     goto error;
     76   }
     77 
     78   allocator = args->allocator ? args->allocator : &mem_default_allocator;
     79   device = (struct scpr_device*)MEM_CALLOC(allocator, 1, sizeof(struct scpr_device));
     80   if(!device) {
     81     res = RES_MEM_ERR;
     82     goto error;
     83   }
     84   ref_init(&device->ref);
     85   device->allocator = allocator;
     86   device->logger = args->logger ? args->logger : LOGGER_DEFAULT;
     87   device->precision = args->precision;
     88   /* to optimize scaling / descaling precision
     89    * set the scale to a power of double's radix (2) (#25) */
     90   device->scale = pow(2, (int)log2(pow(10, device->precision)) + 1);
     91   device->inv_scale = 1/device->scale;
     92   device->range[1] = pow(2, 46 - device->precision);
     93   device->range[0] = -device->range[1];
     94 
     95 exit:
     96   if(out_device) *out_device = device;
     97   return res;
     98 
     99 error:
    100   if(device) {
    101     SCPR(device_ref_put(device));
    102     device = NULL;
    103   }
    104   goto exit;
    105 }
    106 
    107 res_T
    108 scpr_device_ref_get
    109   (struct scpr_device* device)
    110 {
    111   if(!device) return RES_BAD_ARG;
    112   ref_get(&device->ref);
    113   return RES_OK;
    114 }
    115 
    116 res_T
    117 scpr_device_ref_put
    118   (struct scpr_device* device)
    119 {
    120   if(!device) return RES_BAD_ARG;
    121   ref_put(&device->ref, device_release);
    122   return RES_OK;
    123 }
    124 
    125 res_T
    126 scpr_device_get_range
    127   (const struct scpr_device* dev,
    128    double range[2])
    129 {
    130   if(!dev || !range) return RES_BAD_ARG;
    131   d2_set(range, dev->range);
    132   return RES_OK;
    133 }
    134 
    135 res_T
    136 scpr_device_in_range
    137   (const struct scpr_device* dev,
    138    const double* values,
    139    const size_t count,
    140    int* in_range)
    141 
    142 {
    143   size_t i;
    144   int in = 1;
    145   if(!dev || !values || !in_range) return RES_BAD_ARG;
    146   for(i = 0; i < count; i++) {
    147    if(!is_in_range(values[i], dev->range)) {
    148      in = 0;
    149      break;
    150    }
    151   }
    152   *in_range = in;
    153   return RES_OK;
    154 }
    155 
    156 res_T
    157 scpr_device_scale
    158   (const struct scpr_device* dev,
    159    const double* values,
    160    const size_t count,
    161    int64_t* scaled)
    162 {
    163   size_t i;
    164   if(!dev || !values || !scaled) return RES_BAD_ARG;
    165   for(i = 0; i < count; i++) {
    166    if(!is_in_range(values[i], dev->range)) return RES_BAD_ARG;
    167     scaled[i] = std::llround(values[i] * dev->scale);
    168   }
    169   return RES_OK;
    170 }
    171 
    172 res_T
    173 scpr_device_unscale
    174   (const struct scpr_device* dev,
    175    const int64_t* values,
    176    const size_t count,
    177    double* unscaled)
    178 {
    179   size_t i;
    180   if(!dev || !values || !unscaled) return RES_BAD_ARG;
    181   for(i = 0; i < count; i++) {
    182     unscaled[i] = (double)values[i] * dev->inv_scale;
    183   }
    184   return RES_OK;
    185 }