gschem

o_arc.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gschem - gEDA Schematic Capture
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2011 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 #include <config.h>
00021 #include <stdio.h>
00022 #include <math.h>
00023 
00024 #include "gschem.h"
00025 
00026 #ifdef HAVE_LIBDMALLOC
00027 #include <dmalloc.h>
00028 #endif
00029 
00030 
00044 void o_arc_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
00045 {
00046   if (o_current->arc == NULL) {
00047     return;
00048   }
00049 
00050   gschem_cairo_arc (w_current, o_current->line_width,
00051                                o_current->arc->x,
00052                                o_current->arc->y,
00053                                o_current->arc->width / 2,
00054                                o_current->arc->start_angle,
00055                                o_current->arc->end_angle);
00056 
00057   gschem_cairo_set_source_color (w_current,
00058                                  o_drawing_color (w_current, o_current));
00059   gschem_cairo_stroke (w_current, o_current->line_type,
00060                                   o_current->line_end,
00061                                   o_current->line_width,
00062                                   o_current->line_length,
00063                                   o_current->line_space);
00064 
00065   if (o_current->selected && w_current->draw_grips == TRUE) {
00066     o_arc_draw_grips (w_current, o_current);
00067   }
00068 }
00069 
00075 void o_arc_invalidate_rubber (GSCHEM_TOPLEVEL *w_current)
00076 {
00077   int cx, cy, radius;
00078 
00079   WORLDtoSCREEN (w_current, w_current->first_wx, w_current->first_wy, &cx, &cy);
00080   radius = SCREENabs (w_current, w_current->distance);
00081 
00082   /* FIXME: This isn't a tight bounding box */
00083   o_invalidate_rect (w_current, cx - radius, cy - radius,
00084                                 cx + radius, cy + radius);
00085 }
00086 
00100 void o_arc_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current)
00101 {
00102   g_return_if_fail (o_current->arc != NULL);
00103 
00104   gschem_cairo_arc (w_current, 0, o_current->arc->x + dx,
00105                                   o_current->arc->y + dy,
00106                                   o_current->arc->width / 2,
00107                                   o_current->arc->start_angle,
00108                                   o_current->arc->end_angle);
00109 
00110   gschem_cairo_set_source_color (w_current,
00111                                  x_color_lookup_dark (o_current->color));
00112   gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1);
00113 }
00114 
00129 void o_arc_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
00130 {
00131   /* set the center of the arc */
00132   w_current->first_wx = w_x;
00133   w_current->first_wy = w_y;
00134 
00135   /* set the radius */
00136   w_current->distance = 0;
00137 
00138   /* set the start and end angles */
00139   w_current->second_wx = w_current->second_wy = 0;
00140 
00141   /* start the rubberbanding process of the radius */
00142   o_arc_invalidate_rubber (w_current);
00143   w_current->rubber_visible = 1;
00144 }
00145 
00163 void o_arc_end1(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
00164 {
00165   g_assert( w_current->inside_action != 0 );
00166 
00167   /* erases the previous temporary radius segment */
00168   /* o_arc_invalidate_rubber (w_current); */
00169   w_current->rubber_visible = 0;
00170 
00171   /* ack! zero length radius */
00172   if (w_current->distance == 0) {
00173     return;
00174   }
00175 
00176 #if DEBUG
00177   printf("DIST: %d\n", w_current->distance);
00178 #endif
00179 
00180   /* open a dialog to input the start and end angle */
00181   arc_angle_dialog(w_current, NULL);
00182 }
00183 
00197 void o_arc_end4(GSCHEM_TOPLEVEL *w_current, int radius, 
00198         int start_angle, int end_angle)
00199 {
00200   TOPLEVEL *toplevel = w_current->toplevel;
00201   OBJECT *new_obj;
00202 
00203   /* create, initialize and link the new arc object */
00204   new_obj = o_arc_new (toplevel, OBJ_ARC, GRAPHIC_COLOR,
00205                        w_current->first_wx, w_current->first_wy,
00206                        radius, start_angle, end_angle);
00207   s_page_append (toplevel, toplevel->page_current, new_obj);
00208 
00209   w_current->first_wx  = -1;
00210   w_current->first_wy  = -1;
00211   w_current->distance = 0;
00212 
00213   /* Call add-objects-hook */
00214   g_run_hook_object (w_current, "%add-objects-hook", new_obj);
00215 
00216   toplevel->page_current->CHANGED = 1;
00217   
00218   o_undo_savestate(w_current, UNDO_ALL);
00219 }
00220 
00258 void o_arc_motion (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y, int whichone)
00259 {
00260   int diff_x, diff_y, angle_deg;
00261 
00262   /* erase the previous temporary arc */
00263   if (w_current->rubber_visible)
00264     o_arc_invalidate_rubber (w_current);
00265 
00266   if(whichone == ARC_RADIUS) {
00267     /*
00268      * The radius is taken as the biggest distance on the x and y
00269      * axis between the center of the arc and the mouse position.
00270      */     
00271     diff_x = abs(w_current->first_wx - snap_grid (w_current, w_x));
00272     diff_y = abs(w_current->first_wy - snap_grid (w_current, w_y));
00273     w_current->distance = max(diff_x, diff_y);
00274   }
00275   else if((whichone == ARC_START_ANGLE) || (whichone == ARC_END_ANGLE)) {
00276     /* compute the angle */
00277     diff_x = w_x - w_current->first_wx;
00278     diff_y = w_y - w_current->first_wy;
00279     angle_deg = atan2 (diff_y, diff_x) * 180 / M_PI;
00280 
00281     /* set the start or end angle with this angle */
00282     switch(whichone) {
00283     case ARC_START_ANGLE:
00284       w_current->second_wx = (angle_deg + 360) % 360;
00285       break;
00286     
00287     case ARC_END_ANGLE:
00288       w_current->second_wy = (((angle_deg + 360) % 360) -
00289                               w_current->second_wx + 360) % 360;
00290       if (w_current->which_object->arc->end_angle < 0)
00291         w_current->second_wy = w_current->second_wy - 360;
00292       if (w_current->second_wy == 0)
00293         w_current->second_wy = 360;
00294       break;
00295       
00296       // No default required - one of above two branches
00297       // *must* be taken - Coverity ID 201571
00298     }
00299 
00300   }
00301     
00302   /* draw the new temporary arc */
00303   o_arc_invalidate_rubber (w_current);
00304   w_current->rubber_visible = 1;
00305 }
00306 
00318 void o_arc_draw_rubber (GSCHEM_TOPLEVEL *w_current)
00319 {
00320   double rad_angle;
00321   int rdx, rdy;
00322 
00323   gschem_cairo_arc (w_current, 0, w_current->first_wx,
00324                                   w_current->first_wy,
00325                                   w_current->distance,
00326                                   w_current->second_wx,
00327                                   w_current->second_wy);
00328 
00329   gschem_cairo_set_source_color (w_current,
00330                                  x_color_lookup_dark (SELECT_COLOR));
00331 
00332   /* draw the radius line */
00333   rad_angle = ((double) w_current->second_wx) * M_PI / 180;
00334   rdx = (double) w_current->distance * cos (rad_angle);
00335   rdy = (double) w_current->distance * sin (rad_angle);
00336 
00337   gschem_cairo_line (w_current, END_NONE, 0, w_current->first_wx,
00338                                              w_current->first_wy,
00339                                              w_current->first_wx + rdx,
00340                                              w_current->first_wy + rdy);
00341 
00342   gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1);
00343 }
00344 
00353 void o_arc_draw_grips(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
00354 {
00355   double radius, start_angle, end_angle;
00356   int x1, y1, x2, y2, x3, y3;
00357 
00358   if (w_current->draw_grips == FALSE)
00359     return;
00360 
00361   /*
00362    * An arc has three grips:
00363    * <DL>
00364    *   <DT>*</DT><DD>one at the center that allows changes on the
00365    *                 radius - at (<B>x</B>,<B>y</B>).
00366    *   <DT>*</DT><DD>one at the start of the arc - at (<B>x1</B>,<B>y1</B>).
00367    *   <DT>*</DT><DD>one at the end of the arc - at (<B>x2</B>,<B>y2</B>).
00368    */
00369 
00370   x1 = o_current->arc->x;
00371   y1 = o_current->arc->y;
00372 
00373   radius      = o_current->arc->width / 2.;
00374   start_angle = o_current->arc->start_angle;
00375   end_angle   = o_current->arc->end_angle;
00376 
00377   x2 = x1 + radius * cos ( start_angle              * M_PI / 180);
00378   y2 = y1 + radius * sin ( start_angle              * M_PI / 180);
00379   x3 = x1 + radius * cos ((start_angle + end_angle) * M_PI / 180);
00380   y3 = y1 + radius * sin ((start_angle + end_angle) * M_PI / 180);
00381 
00382   /* draw the grip at the center */
00383   o_grips_draw (w_current, x1, y1);
00384 
00385   /* draw the grip at the start_angle end of the arc */
00386   o_grips_draw (w_current, x2, y2);
00387 
00388   /* draw the grip at the end_angle end of the arc */
00389   o_grips_draw (w_current, x3, y3);
00390 
00391 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines