1 /* gEDA - GPL Electronic Design Automation
2  * gschem - gEDA Schematic Capture
3  * Copyright (C) 1998-2010 Ales Hvezda
4  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 #include <config.h>
21 
22 #include <stdio.h>
23 #include <math.h>
24 
25 #include <gschem.h>
26 
27 #ifdef HAVE_LIBDMALLOC
28 #include <dmalloc.h>
29 #endif
30 
31 
32 /*! \brief Convert a x coordinate to mils.
33  *  \par Function Description
34  *  Convert a x coordinate to mils.
35  *
36  *  \param [in] w_current  The GSCHEM_TOPLEVEL object
37  *  \param [in] val        The x coordinate to convert
38  *  \return The coordinate value in mils.
39  */
mil_x(GSCHEM_TOPLEVEL * w_current,int val)40 int mil_x (GSCHEM_TOPLEVEL *w_current, int val)
41 {
42   double i;
43   double fval;
44   int j;
45 
46   fval = val;
47   i = fval * w_current->toplevel->page_current->to_world_x_constant +
48       w_current->toplevel->page_current->left;
49 
50 #ifdef HAS_RINT
51   j = rint(i);
52 #else
53   j = i;
54 #endif
55 
56   return(j);
57 }
58 
59 /*! \brief Convert a y coordinate to mils
60  *  \par Function Description
61  *  Convert a y coordinate to mils
62  *
63  *  \param [in] w_current  The GSCHEM_TOPLEVEL object.
64  *  \param [in] val        The y coordinate to convert.
65  *  \return The coordinate value in mils.
66  */
mil_y(GSCHEM_TOPLEVEL * w_current,int val)67 int mil_y(GSCHEM_TOPLEVEL *w_current, int val)
68 {
69   double i;
70   double fval;
71   int j;
72 
73   fval = w_current->toplevel->height - val;
74   i = fval * w_current->toplevel->page_current->to_world_y_constant +
75       w_current->toplevel->page_current->top;
76 
77 #ifdef HAS_RINT
78   j = rint(i);
79 #else
80   j = i;
81 #endif
82 
83   return(j);
84 }
85 
86 /*! \brief Convert a x coordinate to pixels.
87  *  \par Function Description
88  *  Convert a x coordinate to pixels.
89  *
90  *  \param [in] w_current  The GSCHEM_TOPLEVEL object
91  *  \param [in] val        The x coordinate to convert
92  *  \return The coordinate value in pixels.
93  */
pix_x(GSCHEM_TOPLEVEL * w_current,int val)94 int pix_x (GSCHEM_TOPLEVEL *w_current, int val)
95 {
96 
97   double i;
98   int j;
99 
100   i = w_current->toplevel->page_current->to_screen_x_constant *
101         (double)(val - w_current->toplevel->page_current->left);
102 
103 #ifdef HAS_RINT
104   j = rint(i);
105 #else
106   j = i;
107 #endif
108 
109   /* this is a temp solution to fix the wrapping associated with */
110   /* X coords being greated/less than than 2^15 */
111   if (j >= 32768) {
112     j = 32767;
113   }
114   if (j <= -32768) {
115     j = -32767;
116   }
117 
118   return(j);
119 }
120 
121 /*! \brief Convert a y coordinate to pixels.
122  *  \par Function Description
123  *  Convert a y coordinate to pixels.
124  *
125  *  \param [in] w_current  The GSCHEM_TOPLEVEL object
126  *  \param [in] val        The y coordinate to convert
127  *  \return The coordinate value in pixels.
128  */
pix_y(GSCHEM_TOPLEVEL * w_current,int val)129 int pix_y(GSCHEM_TOPLEVEL *w_current, int val)
130 {
131   double i;
132   int j;
133 
134   i = w_current->toplevel->height -
135         (w_current->toplevel->page_current->to_screen_y_constant *
136          (double)(val - w_current->toplevel->page_current->top));
137 
138 #ifdef HAS_RINT
139   j = rint(i);
140 #else
141   j = i;
142 #endif
143 
144   /* this is a temp solution to fix the wrapping associated with */
145   /* X coords being greated/less than than 2^15 */
146   if (j >= 32768) {
147     j = 32767;
148   }
149   if (j <= -32768) {
150     j = -32767;
151   }
152 
153   return(j);
154 }
155 
156 /*! \brief Transform WORLD coordinates to SCREEN coordinates
157  *  \par Function Description
158  *  This function takes in WORLD x/y coordinates and
159  *  transforms them to SCREEN x/y coordinates.
160  *
161  *  \param [in]  w_current  The GSCHEM_TOPLEVEL object.
162  *  \param [in]  x          The x coordinate in WORLD units.
163  *  \param [in]  y          The y coordinate in WORLD units.
164  *  \param [out] px         The x coordinate in SCREEN units.
165  *  \param [out] py         The y coordinate in SCREEN units.
166  */
WORLDtoSCREEN(GSCHEM_TOPLEVEL * w_current,int x,int y,int * px,int * py)167 void WORLDtoSCREEN (GSCHEM_TOPLEVEL *w_current, int x, int y, int *px, int *py)
168 {
169   *px = pix_x (w_current, x);
170   *py = pix_y (w_current, y);
171 }
172 
173 /*! \brief Transform WORLD coordinates to WORLD coordinates
174  *  \par Function Description
175  *  This function takes in SCREEN x/y coordinates and
176  *  transforms them to WORLD x/y coordinates.
177  *
178  *  \param [in]  w_current  The GSCHEM_TOPLEVEL object.
179  *  \param [in]  mx         The x coordinate in SCREEN units.
180  *  \param [in]  my         The y coordinate in SCREEN units.
181  *  \param [out] x          The x coordinate in WORLD units.
182  *  \param [out] y          The y coordinate in WORLD units.
183  *  \note Question: why are we returning in x and y
184  *                  if this is SCREEN to WORLD shouldn't WORLD
185  *                  coordinates be returned in mx and my?
186  */
SCREENtoWORLD(GSCHEM_TOPLEVEL * w_current,int mx,int my,int * x,int * y)187 void SCREENtoWORLD (GSCHEM_TOPLEVEL *w_current, int mx, int my, int *x, int *y)
188 {
189   *x = mil_x (w_current, mx);
190   *y = mil_y (w_current, my);
191 }
192 
193 /*! \brief Find the closest grid coordinate.
194  *  \par Function Description
195  *  This function snaps the current input coordinate to the
196  *  closest grid coordinate.
197  *
198  *  \param [in] w_current  The GSCHEM_TOPLEVEL object.
199  *  \param [in] input      The coordinate to snap.
200  *  \return The closest grid coordinate to the input.
201  */
snap_grid(GSCHEM_TOPLEVEL * w_current,int input)202 int snap_grid(GSCHEM_TOPLEVEL *w_current, int input)
203 {
204   int p, m, n;
205   int sign, value, snap_grid;
206 
207   if (w_current->snap == SNAP_OFF ||
208       w_current->snap_size <= 0) {
209     return(input);
210   }
211 
212   snap_grid = w_current->snap_size;
213 
214   /* this code was inspired from killustrator, it's much simpler than mine */
215   sign = ( input < 0 ? -1 : 1 );
216   value = abs(input);
217 
218   p = value / snap_grid;
219   m = value % snap_grid;
220   n = p * snap_grid;
221   if (m > snap_grid / 2)
222   n += snap_grid;
223 
224 #if DEBUG
225   printf("p: %d\n", p);
226   printf("m: %d\n", m);
227   printf("m > snap_grid / 2: %d\n", (m > snap_grid / 2));
228   printf("n: %d\n", n);
229   printf("n*s: %d\n", n*sign);
230 #endif
231 
232   return(sign*n);
233 }
234 
235 /*! \brief Get absolute SCREEN coordinate.
236  *  \par Function Description
237  *  Get absolute SCREEN coordinate.
238  *
239  *  \param [in] w_current  The GSCHEM_TOPLEVEL object.
240  *  \param [in] val        The coordinate to convert.
241  *  \return The converted SCREEN coordinate.
242  */
SCREENabs(GSCHEM_TOPLEVEL * w_current,int val)243 int SCREENabs(GSCHEM_TOPLEVEL *w_current, int val)
244 {
245   double f0,f1,f;
246 
247   double i;
248   int j;
249 
250   f0 = w_current->toplevel->page_current->left;
251   f1 = w_current->toplevel->page_current->right;
252   f = w_current->toplevel->width / (f1 - f0);
253   i = f * (double)(val);
254 
255 #ifdef HAS_RINT
256   j = rint(i);
257 #else
258   j = i;
259 #endif
260 
261   return(j);
262 
263 }
264 
265 /*! \brief Get absolute WORLD coordinate.
266  *  \par Function Description
267  *  Get absolute WORLD coordinate.
268  *
269  *  \param [in] w_current  The GSCHEM_TOPLEVEL object.
270  *  \param [in] val        The coordinate to convert.
271  *  \return The converted WORLD coordinate.
272  */
WORLDabs(GSCHEM_TOPLEVEL * w_current,int val)273 int WORLDabs(GSCHEM_TOPLEVEL *w_current, int val)
274 {
275   double fw0,fw1,fw,fval;
276 
277   double i;
278   int j;
279 
280   fw1 = w_current->toplevel->page_current->right;
281   fw0 = w_current->toplevel->page_current->left;
282   fw  = w_current->toplevel->width;
283   fval = val;
284   i = fval * (fw1 - fw0) / fw;
285 
286 #ifdef HAS_RINT
287   j = rint(i);
288 #else
289   j = i;
290 #endif
291 
292   return(j);
293 }
294 
295 
296 /*! \brief */
297 typedef struct st_halfspace HALFSPACE;
298 
299 /*! \brief */
300 struct st_halfspace {
301   int left; /* these are booleans */
302   int top;
303   int right;
304   int bottom;
305 };
306 
307 /* \note
308  * encode_halfspace and clip are part of the cohen-sutherland clipping
309  * algorithm.  They are used to determine if an object is visible or not
310  */
311 /*! \brief Encode WORLD coordinates as halfspace matrix.
312  *  \par Function Description
313  *  This function takes a point and checks if it is in the bounds
314  *  of the current TOPLEVEL object's page coordinates. It
315  *  handles points with WORLD coordinates.
316  *
317  *  \param [in]  w_current  The GSCHEM_TOPLEVEL object.
318  *  \param [in]  point      The point in WORLD coordinates to be checked.
319  *  \param [out] halfspace  The created HALFSPACE structure.
320  *
321  *  \warning halfspace must be allocated before this function is called
322  */
WORLDencode_halfspace(GSCHEM_TOPLEVEL * w_current,sPOINT * point,HALFSPACE * halfspace)323 static void WORLDencode_halfspace (GSCHEM_TOPLEVEL *w_current,
324                                    sPOINT *point, HALFSPACE *halfspace)
325 {
326   halfspace->left = point->x < w_current->toplevel->page_current->left;
327   halfspace->right = point->x > w_current->toplevel->page_current->right;
328   halfspace->bottom = point->y > w_current->toplevel->page_current->bottom;
329   halfspace->top = point->y < w_current->toplevel->page_current->top;
330 }
331 
332 /*! \brief Calculate the cliping region for a set of coordinates.
333  *  \par Function Description
334  *  This function will check the provided set of coordinates to see if
335  *  they fall within a clipping region.  If they do the coordinates will
336  *  be changed to reflect only the region no covered by the clipping window.
337  *  All coordinates should be in WORLD units.
338  *
339  *  \param [in] w_current  The GSCHEM_TOPLEVEL object.
340  *  \param [in,out] x1     x coordinate of the first screen point.
341  *  \param [in,out] y1     y coordinate of the first screen point.
342  *  \param [in,out] x2     x coordinate of the second screen point.
343  *  \param [in,out] y2     y coordinate of the second screen point.
344  *  \return TRUE if coordinates are now visible, FALSE otherwise.
345  */
WORLDclip_change(GSCHEM_TOPLEVEL * w_current,int * x1,int * y1,int * x2,int * y2)346 int WORLDclip_change (GSCHEM_TOPLEVEL *w_current,
347                       int *x1, int *y1, int *x2, int *y2)
348 {
349   HALFSPACE half1, half2;
350   HALFSPACE tmp_half;
351   sPOINT tmp_point;
352   sPOINT point1, point2;
353   float slope;
354   int in1, in2, done;
355   int visible;
356   int w_l, w_t, w_r, w_b;
357 
358   point1.x = *x1;
359   point1.y = *y1;
360   point2.x = *x2;
361   point2.y = *y2;
362 
363   w_l = w_current->toplevel->page_current->left;
364   w_t = w_current->toplevel->page_current->top;
365   w_r = w_current->toplevel->page_current->right;
366   w_b = w_current->toplevel->page_current->bottom;
367 
368   done = FALSE;
369   visible = FALSE;
370 
371   do {
372     WORLDencode_halfspace (w_current, &point1, &half1);
373     WORLDencode_halfspace (w_current, &point2, &half2);
374 
375 #if DEBUG
376     printf("starting loop\n");
377     printf("1 %d %d %d %d\n", half1.left, half1.top, half1.right, half1.bottom);
378     printf("2 %d %d %d %d\n", half2.left, half2.top, half2.right, half2.bottom);
379 #endif
380 
381     in1 = (!half1.left) &&
382       (!half1.top) &&
383       (!half1.right) &&
384       (!half1.bottom);
385 
386     in2 = (!half2.left) &&
387       (!half2.top) &&
388       (!half2.right) &&
389       (!half2.bottom);
390 
391 
392     if (in1 && in2) { /* trivally accept */
393       done = TRUE;
394       visible = TRUE;
395     } else if ( ((half1.left && half2.left) ||
396                  (half1.right && half2.right)) ||
397                 ((half1.top && half2.top) ||
398                  (half1.bottom && half2.bottom)) ) {
399       done = TRUE; /* trivially reject */
400       visible = FALSE;
401     } else { /* at least one point outside */
402       if (in1) {
403         tmp_half = half1;
404         half1 = half2;
405         half2 = tmp_half;
406 
407         tmp_point = point1;
408         point1 = point2;
409         point2 = tmp_point;
410       }
411 
412       if (point2.x == point1.x) { /* vertical line */
413         if (half1.top) {
414           point1.y = w_t;
415         } else if (half1.bottom) {
416           point1.y = w_b;
417         }
418       } else { /* not a vertical line */
419 
420         /* possible fix for alpha core dumping */
421         /* assume the object is visible */
422         if ((point2.x - point1.x) == 0) {
423           return(TRUE);
424         }
425 
426         slope = (float) (point2.y - point1.y) /
427           (float) (point2.x - point1.x);
428 
429         /* possible fix for alpha core dumping */
430         /* assume the object is visible */
431         if (slope == 0.0) {
432           return(TRUE);
433         }
434 
435         if (half1.left) {
436           point1.y = point1.y +
437             (w_l - point1.x) * slope;
438           point1.x = w_l;
439         } else if (half1.right) {
440           point1.y = point1.y +
441             (w_r - point1.x) * slope;
442           point1.x = w_r;
443         } else if (half1.bottom) {
444           point1.x = point1.x +
445             (w_b - point1.y) / slope;
446           point1.y = w_b;
447         } else if (half1.top) {
448           point1.x = point1.x +
449             (w_t - point1.y) / slope;
450           point1.y = w_t;
451         }
452       } /* end of not a vertical line */
453     } /* end of at least one outside */
454   } while (!done);
455 
456   /*printf("after: %d %d %d %d\n", point1.x, point1.y, point2.x, point2.y);*/
457   *x1 = point1.x;
458   *y1 = point1.y;
459   *x2 = point2.x;
460   *y2 = point2.y;
461   return(visible);
462 }
463 
464 /*! \brief Check if a set of coordinates are within a clipping region
465  *  \par Function Description
466  *  This function will check if the given set of coordinates
467  *  are within a clipping region. No action will be taken to change
468  *  the coordinates.
469  *
470  *  \param [in] w_current  The GSCHEM_TOPLEVEL object.
471  *  \param [in,out] x1     x coordinate of the first screen point.
472  *  \param [in,out] y1     y coordinate of the first screen point.
473  *  \param [in,out] x2     x coordinate of the second screen point.
474  *  \param [in,out] y2     y coordinate of the second screen point.
475  *  \return TRUE if coordinates are now visible, FALSE otherwise.
476  */
clip_nochange(GSCHEM_TOPLEVEL * w_current,int x1,int y1,int x2,int y2)477 int clip_nochange (GSCHEM_TOPLEVEL *w_current, int x1, int y1, int x2, int y2)
478 {
479   HALFSPACE half1, half2;
480   HALFSPACE tmp_half;
481   sPOINT tmp_point;
482   sPOINT point1, point2;
483   float slope;
484   int in1, in2, done;
485   int visible;
486   int w_l, w_t, w_r, w_b;
487 
488   point1.x = x1;
489   point1.y = y1;
490   point2.x = x2;
491   point2.y = y2;
492 
493   /*printf("before: %d %d %d %d\n", x1, y1, x2, y2);*/
494 
495   w_l = w_current->toplevel->page_current->left;
496   w_t = w_current->toplevel->page_current->top;
497   w_r = w_current->toplevel->page_current->right;
498   w_b = w_current->toplevel->page_current->bottom;
499 
500   done = FALSE;
501   visible = FALSE;
502 
503   do {
504     WORLDencode_halfspace (w_current, &point1, &half1);
505     WORLDencode_halfspace (w_current, &point2, &half2);
506 
507 #if DEBUG
508     printf("starting loop\n");
509     printf("1 %d %d %d %d\n", half1.left, half1.top, half1.right, half1.bottom);
510     printf("2 %d %d %d %d\n", half2.left, half2.top, half2.right, half2.bottom);
511 #endif
512 
513     in1 = (!half1.left) &&
514       (!half1.top) &&
515       (!half1.right) &&
516       (!half1.bottom);
517 
518     in2 = (!half2.left) &&
519       (!half2.top) &&
520       (!half2.right) &&
521       (!half2.bottom);
522 
523 
524     if (in1 && in2) { /* trivally accept */
525       done = TRUE;
526       visible = TRUE;
527     } else if ( ((half1.left && half2.left) ||
528                  (half1.right && half2.right)) ||
529                 ((half1.top && half2.top) ||
530                  (half1.bottom && half2.bottom)) ) {
531       done = TRUE; /* trivially reject */
532       visible = FALSE;
533     } else { /* at least one point outside */
534       if (in1) {
535         tmp_half = half1;
536         half1 = half2;
537         half2 = tmp_half;
538 
539         tmp_point = point1;
540         point1 = point2;
541         point2 = tmp_point;
542       }
543 
544       if (point2.x == point1.x) { /* vertical line */
545         if (half1.top) {
546           point1.y = w_t;
547         } else if (half1.bottom) {
548           point1.y = w_b;
549         }
550       } else { /* not a vertical line */
551 
552         /* possible fix for alpha core dumping */
553         /* assume the object is visible */
554         if ((point2.x - point1.x) == 0) {
555           return(TRUE);
556         }
557 
558         slope = (float) (point2.y - point1.y) /
559           (float) (point2.x - point1.x);
560 
561         /* possible fix for alpha core dumping */
562         /* assume the object is visible */
563         if (slope == 0.0) {
564           return(TRUE);
565         }
566 
567         if (half1.left) {
568           point1.y = point1.y +
569             (w_l - point1.x) * slope;
570           point1.x = w_l;
571         } else if (half1.right) {
572           point1.y = point1.y +
573             (w_r - point1.x) * slope;
574           point1.x = w_r;
575         } else if (half1.bottom) {
576           point1.x = point1.x +
577             (w_b - point1.y) / slope;
578           point1.y = w_b;
579         } else if (half1.top) {
580           point1.x = point1.x +
581             (w_t - point1.y) / slope;
582           point1.y = w_t;
583         }
584       } /* end of not a vertical line */
585     } /* end of at least one outside */
586   } while (!done);
587 
588   return(visible);
589 }
590 
591 /*! \brief Check if a bounding box is visible on the screen.
592  *  \par Function Description
593  *  This function checks if a given bounding box is visible on the screen.
594  *
595  *  WARNING: top and bottom are mis-named in world-coords,
596  *  top is the smallest "y" value, and bottom is the largest.
597  *  Be careful! This doesn't correspond to what you'd expect.
598  *
599  *  \param [in] w_current  The GSCHEM_TOPLEVEL object.
600  *  \param [in] wleft      Left coordinate of the bounding box.
601  *  \param [in] wtop       Top coordinate of the bounding box.
602  *  \param [in] wright     Right coordinate of the bounding box.
603  *  \param [in] wbottom    Bottom coordinate of the bounding box.
604  *  \return TRUE if bounding box is visible, FALSE otherwise
605  */
visible(GSCHEM_TOPLEVEL * w_current,int wleft,int wtop,int wright,int wbottom)606 int visible (GSCHEM_TOPLEVEL *w_current,
607              int wleft, int wtop, int wright, int wbottom)
608 {
609   int visible=FALSE;
610 
611   /* don't do object clipping if this is false */
612   if (!w_current->toplevel->object_clipping) {
613     return(TRUE);
614   }
615 
616   visible = clip_nochange (w_current, wleft, wtop, wright, wtop);
617 
618 #if DEBUG
619   printf("vis1 %d\n", visible);
620 #endif
621 
622   if (!visible) {
623     visible = clip_nochange (w_current, wleft, wbottom, wright, wbottom);
624   } else {
625     return(visible);
626   }
627 
628 #if DEBUG
629   printf("vis2 %d\n", visible);
630 #endif
631 
632   if (!visible) {
633     visible = clip_nochange (w_current, wleft, wtop, wleft, wbottom);
634   } else {
635     return(visible);
636   }
637 
638 #if DEBUG
639   printf("vis3 %d\n", visible);
640 #endif
641 
642   if (!visible) {
643     visible = clip_nochange (w_current, wright, wtop, wright, wbottom);
644   } else {
645     return(visible);
646   }
647 
648 #if DEBUG
649   printf("vis4 %d\n", visible);
650 #endif
651 
652 #if DEBUG
653   printf("%d %d %d\n", wleft, w_current->toplevel->page_current->top, wright);
654   printf("%d %d %d\n", wtop, w_current->toplevel->page_current->top, wbottom);
655   printf("%d %d %d\n", wleft, w_current->toplevel->page_current->right, wright);
656   printf("%d %d %d\n", wtop, w_current->toplevel->page_current->bottom, wbottom);
657 #endif
658 
659   /*
660    * now check to see if bounding box encompasses the entire viewport.
661    * We only need to test if one point on the screen clipping boundary
662    * is indide the bounding box of the object.
663    */
664   if (w_current->toplevel->page_current->left >= wleft  &&
665       w_current->toplevel->page_current->left <= wright &&
666       w_current->toplevel->page_current->top >= wtop    &&
667       w_current->toplevel->page_current->top <= wbottom ) {
668     visible = 1;
669   }
670 
671 #if DEBUG
672   printf("vis5 %d\n", visible);
673 #endif
674 
675   return(visible);
676 }
677 
678 
679 /*! \brief Rounds numbers by a power of 10.
680  *  \par Function Description
681  *  This function will round numbers using a power of 10 method.
682  *  For example:
683  *                1235 rounds to 1000
684  *                 670 rounds to  500
685  *               0.234 rounds to  0.2
686  *  integer values would be enough if there are no numbers smaller than 1 (hw)
687  *
688  *  \param [in] unrounded  The number to be rounded.
689  *  \return The rounded number.
690  */
691 /* rounds for example 1235 to 1000, 670 to 500, 0.234 to 0.2 ...
692 int would be enough if there are no numbers smaller 1 (hw)*/
round_5_2_1(double unrounded)693 double round_5_2_1(double unrounded)
694 {
695   int digits;
696   double betw_1_10;
697 
698   /*only using the automatic cast */
699   digits = log10(unrounded);
700   /* creates numbers between 1 and 10 */
701   betw_1_10 = unrounded / pow(10,digits);
702 
703   if (betw_1_10 < 1.5) {
704     return(pow(10,digits));
705   }
706   if (betw_1_10 > 1.4 && betw_1_10 < 3.5 ) {
707     return(2*pow(10,digits));
708   }
709   if (betw_1_10 > 3.4 && betw_1_10 < 7.5 ) {
710     return(5*pow(10,digits));
711   }
712   else {
713     return(10*pow(10,digits));
714   }
715 }
716