1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2020 gEDA Contributors (see ChangeLog for details)
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.
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.
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
27 /*! \brief Find the closest grid coordinate.
28 * \par Function Description
29 * This function snaps the current input coordinate to the
30 * closest grid coordinate.
32 * \param [in] w_current The GschemToplevel object.
33 * \param [in] input The coordinate to snap.
34 * \return The closest grid coordinate to the input.
36 int snap_grid(GschemToplevel
*w_current
, int input
)
39 int sign
, value
, snap_size
;
42 snap_mode
= gschem_options_get_snap_mode (w_current
->options
);
43 snap_size
= gschem_options_get_snap_size (w_current
->options
);
45 if (snap_mode
== SNAP_OFF
) {
49 /* this code was inspired from killustrator, it's much simpler than mine */
50 sign
= ( input
< 0 ? -1 : 1 );
53 p
= value
/ snap_size
;
54 m
= value
% snap_size
;
56 if (m
> snap_size
/ 2)
62 printf("m > snap_size / 2: %d\n", (m
> snap_size
/ 2));
64 printf("n*s: %d\n", n
*sign
);
73 typedef struct st_halfspace HALFSPACE
;
77 int left
; /* these are booleans */
84 * encode_halfspace and clip are part of the cohen-sutherland clipping
85 * algorithm. They are used to determine if an object is visible or not
87 /*! \brief Encode WORLD coordinates as halfspace matrix.
88 * \par Function Description
89 * This function takes a point and checks if it is in the bounds
90 * of the current TOPLEVEL object's page coordinates. It
91 * handles points with WORLD coordinates.
93 * \param [in] w_current The GschemToplevel object.
94 * \param [in] point The point in WORLD coordinates to be checked.
95 * \param [out] halfspace The created HALFSPACE structure.
97 * \warning halfspace must be allocated before this function is called
99 static void WORLDencode_halfspace (GschemPageGeometry
*geometry
,
100 sPOINT
*point
, HALFSPACE
*halfspace
)
102 halfspace
->left
= point
->x
< geometry
->viewport_left
;
103 halfspace
->right
= point
->x
> geometry
->viewport_right
;
104 halfspace
->bottom
= point
->y
> geometry
->viewport_bottom
;
105 halfspace
->top
= point
->y
< geometry
->viewport_top
;
108 /*! \brief Check if a set of coordinates are within a clipping region
109 * \par Function Description
110 * This function will check if the given set of coordinates
111 * are within a clipping region. No action will be taken to change
114 * \param [in] w_current The GschemToplevel object.
115 * \param [in,out] x1 x coordinate of the first screen point.
116 * \param [in,out] y1 y coordinate of the first screen point.
117 * \param [in,out] x2 x coordinate of the second screen point.
118 * \param [in,out] y2 y coordinate of the second screen point.
119 * \return TRUE if coordinates are now visible, FALSE otherwise.
121 int clip_nochange (GschemPageGeometry
*geometry
, int x1
, int y1
, int x2
, int y2
)
123 HALFSPACE half1
, half2
;
126 sPOINT point1
, point2
;
130 int w_l
, w_t
, w_r
, w_b
;
137 /*printf("before: %d %d %d %d\n", x1, y1, x2, y2);*/
139 w_l
= geometry
->viewport_left
;
140 w_t
= geometry
->viewport_top
;
141 w_r
= geometry
->viewport_right
;
142 w_b
= geometry
->viewport_bottom
;
148 WORLDencode_halfspace (geometry
, &point1
, &half1
);
149 WORLDencode_halfspace (geometry
, &point2
, &half2
);
152 printf("starting loop\n");
153 printf("1 %d %d %d %d\n", half1
.left
, half1
.top
, half1
.right
, half1
.bottom
);
154 printf("2 %d %d %d %d\n", half2
.left
, half2
.top
, half2
.right
, half2
.bottom
);
157 in1
= (!half1
.left
) &&
162 in2
= (!half2
.left
) &&
168 if (in1
&& in2
) { /* trivally accept */
171 } else if ( ((half1
.left
&& half2
.left
) ||
172 (half1
.right
&& half2
.right
)) ||
173 ((half1
.top
&& half2
.top
) ||
174 (half1
.bottom
&& half2
.bottom
)) ) {
175 done
= TRUE
; /* trivially reject */
177 } else { /* at least one point outside */
188 if (point2
.x
== point1
.x
) { /* vertical line */
191 } else if (half1
.bottom
) {
194 } else { /* not a vertical line */
196 /* possible fix for alpha core dumping */
197 /* assume the object is visible */
198 if ((point2
.x
- point1
.x
) == 0) {
202 slope
= (float) (point2
.y
- point1
.y
) /
203 (float) (point2
.x
- point1
.x
);
205 /* possible fix for alpha core dumping */
206 /* assume the object is visible */
212 point1
.y
= point1
.y
+
213 (w_l
- point1
.x
) * slope
;
215 } else if (half1
.right
) {
216 point1
.y
= point1
.y
+
217 (w_r
- point1
.x
) * slope
;
219 } else if (half1
.bottom
) {
220 point1
.x
= point1
.x
+
221 (w_b
- point1
.y
) / slope
;
223 } else if (half1
.top
) {
224 point1
.x
= point1
.x
+
225 (w_t
- point1
.y
) / slope
;
228 } /* end of not a vertical line */
229 } /* end of at least one outside */
235 /*! \brief Check if a bounding box is visible on the screen.
236 * \par Function Description
237 * This function checks if a given bounding box is visible on the screen.
239 * WARNING: top and bottom are mis-named in world-coords,
240 * top is the smallest "y" value, and bottom is the largest.
241 * Be careful! This doesn't correspond to what you'd expect.
243 * \param [in] w_current The GschemToplevel object.
244 * \param [in] wleft Left coordinate of the bounding box.
245 * \param [in] wtop Top coordinate of the bounding box.
246 * \param [in] wright Right coordinate of the bounding box.
247 * \param [in] wbottom Bottom coordinate of the bounding box.
248 * \return TRUE if bounding box is visible, FALSE otherwise
250 int visible (GschemToplevel
*w_current
,
251 int wleft
, int wtop
, int wright
, int wbottom
)
254 GschemPageGeometry
*geometry
= gschem_page_view_get_page_geometry (gschem_toplevel_get_current_page_view (w_current
));
256 visible
= clip_nochange (geometry
, wleft
, wtop
, wright
, wtop
);
259 printf("vis1 %d\n", visible
);
263 visible
= clip_nochange (geometry
, wleft
, wbottom
, wright
, wbottom
);
269 printf("vis2 %d\n", visible
);
273 visible
= clip_nochange (geometry
, wleft
, wtop
, wleft
, wbottom
);
279 printf("vis3 %d\n", visible
);
283 visible
= clip_nochange (geometry
, wright
, wtop
, wright
, wbottom
);
289 printf("vis4 %d\n", visible
);
293 printf("%d %d %d\n", wleft
, geometry
->viewport_top
, wright
);
294 printf("%d %d %d\n", wtop
, geometry
->viewport_top
, wbottom
);
295 printf("%d %d %d\n", wleft
, geometry
->viewport_right
, wright
);
296 printf("%d %d %d\n", wtop
, geometry
->viewport_bottom
, wbottom
);
300 * now check to see if bounding box encompasses the entire viewport.
301 * We only need to test if one point on the screen clipping boundary
302 * is indide the bounding box of the object.
304 if (geometry
->viewport_left
>= wleft
&&
305 geometry
->viewport_left
<= wright
&&
306 geometry
->viewport_top
>= wtop
&&
307 geometry
->viewport_top
<= wbottom
) {
312 printf("vis5 %d\n", visible
);
319 /*! \brief Rounds numbers by a power of 10.
320 * \par Function Description
321 * This function will round numbers using a power of 10 method.
323 * 1235 rounds to 1000
325 * 0.234 rounds to 0.2
326 * integer values would be enough if there are no numbers smaller than 1 (hw)
328 * \param [in] unrounded The number to be rounded.
329 * \return The rounded number.
331 /* rounds for example 1235 to 1000, 670 to 500, 0.234 to 0.2 ...
332 int would be enough if there are no numbers smaller 1 (hw)*/
333 double round_5_2_1(double unrounded
)
338 /*only using the automatic cast */
339 digits
= log10(unrounded
);
340 /* creates numbers between 1 and 10 */
341 betw_1_10
= unrounded
/ pow(10,digits
);
343 if (betw_1_10
< 1.5) {
344 return(pow(10,digits
));
346 if (betw_1_10
> 1.4 && betw_1_10
< 3.5 ) {
347 return(2*pow(10,digits
));
349 if (betw_1_10
> 3.4 && betw_1_10
< 7.5 ) {
350 return(5*pow(10,digits
));
353 return(10*pow(10,digits
));