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
26 /*! \todo Finish function documentation!!!
28 * \par Function Description
31 void o_arc_invalidate_rubber (GschemToplevel
*w_current
)
33 g_return_if_fail (w_current
!= NULL
);
35 GschemPageView
*page_view
= gschem_toplevel_get_current_page_view (w_current
);
37 /* FIXME: This isn't a tight bounding box */
39 gschem_page_view_invalidate_world_rect (page_view
,
40 w_current
->first_wx
- w_current
->distance
,
41 w_current
->first_wy
- w_current
->distance
,
42 w_current
->first_wx
+ w_current
->distance
,
43 w_current
->first_wy
+ w_current
->distance
);
46 /*! \brief Start process to input a new arc.
47 * \par Function Description
48 * This function starts the process to input a new arc. Parameters for
49 * this arc are put into/extracted from the <B>w_current</B> toplevel structure.
50 * <B>w_x</B> and <B>w_y</B> are current coordinates of the pointer in screen unit.
52 * First step of the arc input is to set the radius of the arc. The center
53 * of the arc is kept in (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>).
54 * The radius of the arc is in <B>w_current->distance</B>.
56 * \param [in] w_current The GschemToplevel object.
57 * \param [in] w_x Current x coordinate of pointer in world units.
58 * \param [in] w_y Current y coordinate of pointer in world units.
60 void o_arc_start(GschemToplevel
*w_current
, int w_x
, int w_y
)
62 i_action_start (w_current
);
64 /* set the center of the arc */
65 w_current
->first_wx
= w_x
;
66 w_current
->first_wy
= w_y
;
69 w_current
->distance
= 0;
71 /* set the start and end angles */
72 w_current
->second_wx
= w_current
->second_wy
= 0;
74 /* start the rubberbanding process of the radius */
75 o_arc_invalidate_rubber (w_current
);
76 w_current
->rubber_visible
= 1;
79 /*! \brief End the input of an arc.
80 * \par Function Description
81 * This function ends the input of the radius of the arc.
82 * The (<B>w_x</B>,<B>w_y</B>) point is taken as the other end of the radius segment.
83 * The distance between this point and the center is the radius of the arc.
84 * <B>w_x</B> and <B>w_y</B> are in world coords.
86 * At the end of this function, the center of the arc is at
87 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>) and its radius is
88 * <B>w_current->distance</B>.
90 * The two angles needs to be input to fully define the arc.
92 * \param [in] w_current The GschemToplevel object.
93 * \param [in] w_x (unused)
94 * \param [in] w_y (unused)
96 void o_arc_end1(GschemToplevel
*w_current
, int w_x
, int w_y
)
98 g_assert( w_current
->inside_action
!= 0 );
100 /* erases the previous temporary radius segment */
101 /* o_arc_invalidate_rubber (w_current); */
102 w_current
->rubber_visible
= 0;
104 /* ack! zero length radius */
105 if (w_current
->distance
!= 0) {
108 printf("DIST: %d\n", w_current
->distance
);
111 /* open a dialog to input the start and end angle */
112 arc_angle_dialog(w_current
, NULL
);
115 i_action_stop (w_current
);
118 /*! \brief Ends the process of arc input.
119 * \par Function Description
120 * The #o_arc_end4() function ends the process of the input of an arc.
121 * <B>start_angle</B> and <B>sweep_angle</B> are the start and sweep angle of the
122 * arc in degrees. The partial internal representation of the arc, i.e.
123 * the center and the radius of the arc, are converted in world units.
124 * A new object is created and linked to the object list.
126 * \param [in] w_current The GschemToplevel object.
127 * \param [in] radius Radius of the arc
128 * \param [in] start_angle Start of angle in degrees.
129 * \param [in] sweep_angle Angle sweep in degrees.
131 void o_arc_end4(GschemToplevel
*w_current
, int radius
,
132 int start_angle
, int sweep_angle
)
134 GschemPageView
*page_view
= gschem_toplevel_get_current_page_view (w_current
);
135 g_return_if_fail (page_view
!= NULL
);
137 PAGE
*page
= gschem_page_view_get_page (page_view
);
138 g_return_if_fail (page
!= NULL
);
140 TOPLEVEL
*toplevel
= page
->toplevel
;
141 g_return_if_fail (toplevel
!= NULL
);
145 /* create, initialize and link the new arc object */
146 new_obj
= o_arc_new (toplevel
, GRAPHIC_COLOR
,
147 w_current
->first_wx
, w_current
->first_wy
,
148 radius
, start_angle
, sweep_angle
);
149 s_page_append (toplevel
, page
, new_obj
);
151 w_current
->first_wx
= -1;
152 w_current
->first_wy
= -1;
153 w_current
->distance
= 0;
155 /* Call add-objects-hook */
156 g_run_hook_object (w_current
, "%add-objects-hook", new_obj
);
158 gschem_toplevel_page_content_changed (w_current
, page
);
159 o_undo_savestate (w_current
, page
, UNDO_ALL
, _("Arc"));
162 /*! \brief Draw an arc using one angle modification.
163 * \par Function Description
164 * This function draws an arc according to its internal representation
165 * and allows the modification of one of its angle. The start or end
166 * angle of the arc is updated according to <B>whichone</B> with the angle
167 * that the current pointer and the arc center are making with the horizontal.
169 * The previous temporary arc is erased, the angle is then computed
170 * and updated and finally a new temporary arc with the new angle is drawn.
172 * The arc is internally described by :
174 * <DT>*</DT><DD>(<B>w_current->first_wx</B>,<B>w_current->first_wy</B>) as
176 * <DT>*</DT><DD><B>w_current->distance</B> as its radius.
177 * <DT>*</DT><DD><B>w_current->second_wx</B> and <B>w_current->second_wx</B> as its
178 * start and end angle respectively.
181 * \param [in] w_current The GschemToplevel object.
182 * \param [in] w_x Current x coordinate of pointer in world units.
183 * \param [in] w_y Current y coordinate of pointer in world units.
184 * \param [in] whichone Which angle to change.
186 * <B>whichone</B> can have one of the following values:
188 * <DT>ARC_RADIUS</DT>
189 * <DD>at the center of the arc. This grip is used to modify
190 * the radius of the arc.
191 * <DT>ARC_START_ANGLE</DT>
192 * <DD>at one end of the arc. It corresponds to the starting
194 * <DT>ARC_SWEEP_ANGLE</DT>
195 * <DD>at the other end of the arc. It corresponds to the
196 * ending angle of the arc.
199 void o_arc_motion (GschemToplevel
*w_current
, int w_x
, int w_y
, int whichone
)
201 int diff_x
, diff_y
, angle_deg
;
203 g_assert (w_current
->inside_action
!= 0);
205 /* erase the previous temporary arc */
206 if (w_current
->rubber_visible
)
207 o_arc_invalidate_rubber (w_current
);
209 if(whichone
== ARC_RADIUS
) {
211 * The radius is taken as the biggest distance on the x and y
212 * axis between the center of the arc and the mouse position.
214 diff_x
= abs(w_current
->first_wx
- snap_grid (w_current
, w_x
));
215 diff_y
= abs(w_current
->first_wy
- snap_grid (w_current
, w_y
));
216 w_current
->distance
= max(diff_x
, diff_y
);
218 else if((whichone
== ARC_START_ANGLE
) || (whichone
== ARC_SWEEP_ANGLE
)) {
219 /* compute the angle */
220 diff_x
= w_x
- w_current
->first_wx
;
221 diff_y
= w_y
- w_current
->first_wy
;
222 angle_deg
= atan2 (diff_y
, diff_x
) * 180 / M_PI
;
224 /* set the start or end angle with this angle */
226 case ARC_START_ANGLE
:
227 w_current
->second_wx
= (angle_deg
+ 360) % 360;
230 case ARC_SWEEP_ANGLE
:
231 w_current
->second_wy
= (((angle_deg
+ 360) % 360) -
232 w_current
->second_wx
+ 360) % 360;
233 if (w_current
->which_object
->arc
->sweep_angle
< 0)
234 w_current
->second_wy
= w_current
->second_wy
- 360;
235 if (w_current
->second_wy
== 0)
236 w_current
->second_wy
= 360;
240 * No default required - one of above two branches
241 * *must* be taken - Coverity ID 201571
247 /* draw the new temporary arc */
248 o_arc_invalidate_rubber (w_current
);
249 w_current
->rubber_visible
= 1;
252 /*! \brief Draw arc from GschemToplevel object.
253 * \par Function Description
254 * This function draws the arc from the variables in the GschemToplevel
255 * structure <B>*w_current</B>.
256 * The center of the arc is at (<B>w_current->first_wx</B>,
257 * <B>w_current->first_wy</B>), its radius equal to <B>w_current->distance</B>,
258 * and the start and end angle are given by <B>w_current->second_wx</B> and
259 * <B>w_current->second_wy</B>.
261 * \param [in] w_current The GschemToplevel object.
263 void o_arc_draw_rubber (GschemToplevel
*w_current
, EdaRenderer
*renderer
)
268 cairo_t
*cr
= eda_renderer_get_cairo_context (renderer
);
269 GArray
*color_map
= eda_renderer_get_color_map (renderer
);
270 int flags
= eda_renderer_get_cairo_flags (renderer
);
272 eda_cairo_arc (cr
, flags
, wwidth
,
273 w_current
->first_wx
, w_current
->first_wy
,
275 w_current
->second_wx
, w_current
->second_wy
);
277 eda_cairo_set_source_color (cr
, SELECT_COLOR
, color_map
);
279 /* draw the radius line */
280 rad_angle
= ((double) w_current
->second_wx
) * M_PI
/ 180;
281 rdx
= (double) w_current
->distance
* cos (rad_angle
);
282 rdy
= (double) w_current
->distance
* sin (rad_angle
);
284 eda_cairo_line (cr
, flags
, END_NONE
, wwidth
,
285 w_current
->first_wx
, w_current
->first_wy
,
286 w_current
->first_wx
+ rdx
, w_current
->first_wy
+ rdy
);
288 eda_cairo_stroke (cr
, flags
, TYPE_SOLID
, END_NONE
, wwidth
, -1, -1);