pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 00033 #ifdef HAVE_CONFIG_H 00034 #include "config.h" 00035 #endif 00036 00037 #include "global.h" 00038 00039 #include "copy.h" 00040 #include "create.h" 00041 #include "crosshair.h" 00042 #include "data.h" 00043 #include "draw.h" 00044 #include "insert.h" 00045 #include "line.h" 00046 #include "misc.h" 00047 #include "move.h" 00048 #include "polygon.h" 00049 #include "rtree.h" 00050 #include "search.h" 00051 #include "select.h" 00052 #include "set.h" 00053 #include "undo.h" 00054 00055 #ifdef HAVE_LIBDMALLOC 00056 #include <dmalloc.h> 00057 #endif 00058 00059 /* --------------------------------------------------------------------------- 00060 * some local prototypes 00061 */ 00062 static void *InsertPointIntoLine (LayerType *, LineType *); 00063 static void *InsertPointIntoPolygon (LayerType *, PolygonType *); 00064 static void *InsertPointIntoRat (RatType *); 00065 00066 /* --------------------------------------------------------------------------- 00067 * some local identifiers 00068 */ 00069 static Coord InsertX, InsertY; /* used by local routines as offset */ 00070 static Cardinal InsertAt; 00071 static bool InsertLast; 00072 static bool Forcible; 00073 static ObjectFunctionType InsertFunctions = { 00074 InsertPointIntoLine, 00075 NULL, 00076 InsertPointIntoPolygon, 00077 NULL, 00078 NULL, 00079 NULL, 00080 NULL, 00081 NULL, 00082 NULL, 00083 NULL, 00084 NULL, 00085 InsertPointIntoRat 00086 }; 00087 00091 static void * 00092 InsertPointIntoRat (RatType *Rat) 00093 { 00094 LineType *newone; 00095 00096 newone = CreateDrawnLineOnLayer (CURRENT, Rat->Point1.X, Rat->Point1.Y, 00097 InsertX, InsertY, Settings.LineThickness, 00098 2 * Settings.Keepaway, Rat->Flags); 00099 if (!newone) 00100 return newone; 00101 AddObjectToCreateUndoList (LINE_TYPE, CURRENT, newone, newone); 00102 EraseRat (Rat); 00103 DrawLine (CURRENT, newone); 00104 newone = CreateDrawnLineOnLayer (CURRENT, Rat->Point2.X, Rat->Point2.Y, 00105 InsertX, InsertY, Settings.LineThickness, 00106 2 * Settings.Keepaway, Rat->Flags); 00107 if (newone) 00108 { 00109 AddObjectToCreateUndoList (LINE_TYPE, CURRENT, newone, newone); 00110 DrawLine (CURRENT, newone); 00111 } 00112 MoveObjectToRemoveUndoList (RATLINE_TYPE, Rat, Rat, Rat); 00113 Draw (); 00114 return (newone); 00115 } 00116 00120 static void * 00121 InsertPointIntoLine (LayerType *Layer, LineType *Line) 00122 { 00123 LineType *line; 00124 Coord X, Y; 00125 00126 if (((Line->Point1.X == InsertX) && (Line->Point1.Y == InsertY)) || 00127 ((Line->Point2.X == InsertX) && (Line->Point2.Y == InsertY))) 00128 return (NULL); 00129 X = Line->Point2.X; 00130 Y = Line->Point2.Y; 00131 AddObjectToMoveUndoList (LINEPOINT_TYPE, Layer, Line, &Line->Point2, 00132 InsertX - X, InsertY - Y); 00133 EraseLine (Line); 00134 r_delete_entry (Layer->line_tree, (BoxType *) Line); 00135 RestoreToPolygon (PCB->Data, LINE_TYPE, Layer, Line); 00136 Line->Point2.X = InsertX; 00137 Line->Point2.Y = InsertY; 00138 SetLineBoundingBox (Line); 00139 r_insert_entry (Layer->line_tree, (BoxType *) Line, 0); 00140 ClearFromPolygon (PCB->Data, LINE_TYPE, Layer, Line); 00141 DrawLine (Layer, Line); 00142 /* we must create after playing with Line since creation may 00143 * invalidate the line pointer 00144 */ 00145 if ((line = CreateDrawnLineOnLayer (Layer, InsertX, InsertY, 00146 X, Y, 00147 Line->Thickness, Line->Clearance, 00148 Line->Flags))) 00149 { 00150 AddObjectToCreateUndoList (LINE_TYPE, Layer, line, line); 00151 DrawLine (Layer, line); 00152 ClearFromPolygon (PCB->Data, LINE_TYPE, Layer, line); 00153 /* creation call adds it to the rtree */ 00154 } 00155 Draw (); 00156 return (line); 00157 } 00158 00162 static void * 00163 InsertPointIntoPolygon (LayerType *Layer, PolygonType *Polygon) 00164 { 00165 PointType save; 00166 Cardinal n; 00167 LineType line; 00168 00169 if (!Forcible) 00170 { 00171 /* 00172 * first make sure adding the point is sensible 00173 */ 00174 line.Thickness = 0; 00175 line.Point1 = Polygon->Points[prev_contour_point (Polygon, InsertAt)]; 00176 line.Point2 = Polygon->Points[InsertAt]; 00177 if (IsPointOnLine ((float) InsertX, (float) InsertY, 0.0, &line)) 00178 return (NULL); 00179 } 00180 /* 00181 * second, shift the points up to make room for the new point 00182 */ 00183 ErasePolygon (Polygon); 00184 r_delete_entry (Layer->polygon_tree, (BoxType *) Polygon); 00185 save = *CreateNewPointInPolygon (Polygon, InsertX, InsertY); 00186 for (n = Polygon->PointN - 1; n > InsertAt; n--) 00187 Polygon->Points[n] = Polygon->Points[n - 1]; 00188 00189 /* Shift up indices of any holes */ 00190 for (n = 0; n < Polygon->HoleIndexN; n++) 00191 if (Polygon->HoleIndex[n] > InsertAt || 00192 (InsertLast && Polygon->HoleIndex[n] == InsertAt)) 00193 Polygon->HoleIndex[n]++; 00194 00195 Polygon->Points[InsertAt] = save; 00196 SetChangedFlag (true); 00197 AddObjectToInsertPointUndoList (POLYGONPOINT_TYPE, Layer, Polygon, 00198 &Polygon->Points[InsertAt]); 00199 00200 SetPolygonBoundingBox (Polygon); 00201 r_insert_entry (Layer->polygon_tree, (BoxType *) Polygon, 0); 00202 InitClip (PCB->Data, Layer, Polygon); 00203 if (Forcible || !RemoveExcessPolygonPoints (Layer, Polygon)) 00204 { 00205 DrawPolygon (Layer, Polygon); 00206 Draw (); 00207 } 00208 return (&Polygon->Points[InsertAt]); 00209 } 00210 00214 void * 00215 InsertPointIntoObject (int Type, void *Ptr1, void *Ptr2, Cardinal * Ptr3, 00216 Coord DX, Coord DY, bool Force, 00217 bool insert_last) 00218 { 00219 void *ptr; 00220 00221 /* setup offset */ 00222 InsertX = DX; 00223 InsertY = DY; 00224 InsertAt = *Ptr3; 00225 InsertLast = insert_last; 00226 Forcible = Force; 00227 00228 /* the operation insert the points to the undo-list */ 00229 ptr = ObjectOperation (&InsertFunctions, Type, Ptr1, Ptr2, Ptr3); 00230 if (ptr != NULL) 00231 IncrementUndoSerialNumber (); 00232 return (ptr); 00233 } 00234 00238 PointType * 00239 AdjustInsertPoint (void) 00240 { 00241 static PointType InsertedPoint; 00242 double m; 00243 Coord x, y, m1, m2; 00244 LineType *line = (LineType *) Crosshair.AttachedObject.Ptr2; 00245 00246 if (Crosshair.AttachedObject.State == STATE_FIRST) 00247 return NULL; 00248 Crosshair.AttachedObject.Ptr3 = &InsertedPoint; 00249 if (gui->shift_is_pressed ()) 00250 { 00251 AttachedLineType myline; 00252 /* only force 45 degree for nearest point */ 00253 if (Distance (Crosshair.X, Crosshair.Y, line->Point1.X, line->Point1.Y) < 00254 Distance (Crosshair.X, Crosshair.Y, line->Point2.X, line->Point2.Y)) 00255 myline.Point1 = myline.Point2 = line->Point1; 00256 else 00257 myline.Point1 = myline.Point2 = line->Point2; 00258 FortyFiveLine (&myline); 00259 InsertedPoint.X = myline.Point2.X; 00260 InsertedPoint.Y = myline.Point2.Y; 00261 return &InsertedPoint; 00262 } 00263 if (PCB->RatDraw || TEST_FLAG (ALLDIRECTIONFLAG, PCB)) 00264 { 00265 InsertedPoint.X = Crosshair.X; 00266 InsertedPoint.Y = Crosshair.Y; 00267 return &InsertedPoint; 00268 } 00269 if (Crosshair.X == line->Point1.X) 00270 m1 = 2; /* 2 signals infinite slope */ 00271 else 00272 { 00273 m = (double) (Crosshair.Y - line->Point1.Y) / (Crosshair.X - line->Point1.X); 00274 m1 = 0; 00275 if (m > TAN_30_DEGREE) 00276 m1 = (m > TAN_60_DEGREE) ? 2 : 1; 00277 else if (m < -TAN_30_DEGREE) 00278 m1 = (m < -TAN_60_DEGREE) ? 2 : -1; 00279 } 00280 if (Crosshair.X == line->Point2.X) 00281 m2 = 2; /* 2 signals infinite slope */ 00282 else 00283 { 00284 m = (double) (Crosshair.Y - line->Point2.Y) / (Crosshair.X - line->Point2.X); 00285 m2 = 0; 00286 if (m > TAN_30_DEGREE) 00287 m2 = (m > TAN_60_DEGREE) ? 2 : 1; 00288 else if (m < -TAN_30_DEGREE) 00289 m2 = (m < -TAN_60_DEGREE) ? 2 : -1; 00290 } 00291 if (m1 == m2) 00292 { 00293 InsertedPoint.X = line->Point1.X; 00294 InsertedPoint.Y = line->Point1.Y; 00295 return &InsertedPoint; 00296 } 00297 if (m1 == 2) 00298 { 00299 x = line->Point1.X; 00300 y = line->Point2.Y + m2 * (line->Point1.X - line->Point2.X); 00301 } 00302 else if (m2 == 2) 00303 { 00304 x = line->Point2.X; 00305 y = line->Point1.Y + m1 * (line->Point2.X - line->Point1.X); 00306 } 00307 else 00308 { 00309 x = (line->Point2.Y - line->Point1.Y + m1 * line->Point1.X 00310 - m2 * line->Point2.X) / (m1 - m2); 00311 y = (m1 * line->Point2.Y - m1 * m2 * line->Point2.X 00312 - m2 * line->Point1.Y + m1 * m2 * line->Point1.X) / (m1 - m2); 00313 } 00314 InsertedPoint.X = x; 00315 InsertedPoint.Y = y; 00316 return &InsertedPoint; 00317 }