6 * PCB, interactive printed circuit board design
7 * Copyright (C) 1994,1995,1996 Thomas Nau
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * Contact addresses for paper mail and Email:
24 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
25 * Thomas.Nau@rz.uni-ulm.de
30 /* functions used to insert points into objects
41 #include "crosshair.h"
55 #ifdef HAVE_LIBDMALLOC
64 /* ---------------------------------------------------------------------------
65 * some local prototypes
67 static void *InsertPointIntoLine (LayerTypePtr
, LineTypePtr
);
68 static void *InsertPointIntoPolygon (LayerTypePtr
, PolygonTypePtr
);
69 static void *InsertPointIntoRat (RatTypePtr
);
71 /* ---------------------------------------------------------------------------
72 * some local identifiers
74 static LocationType InsertX
, /* used by local routines as offset */
76 static Cardinal InsertAt
;
77 static bool InsertLast
;
79 static ObjectFunctionType InsertFunctions
= {
82 InsertPointIntoPolygon
,
94 /* ---------------------------------------------------------------------------
95 * inserts a point into a rat-line
98 InsertPointIntoRat (RatTypePtr Rat
)
102 new = CreateDrawnLineOnLayer (CURRENT
, Rat
->Point1
.X
, Rat
->Point1
.Y
,
103 InsertX
, InsertY
, Settings
.LineThickness
,
104 2 * Settings
.Keepaway
, Rat
->Flags
);
107 AddObjectToCreateUndoList (LINE_TYPE
, CURRENT
, new, new);
109 DrawLine (CURRENT
, new, 0);
110 new = CreateDrawnLineOnLayer (CURRENT
, Rat
->Point2
.X
, Rat
->Point2
.Y
,
111 InsertX
, InsertY
, Settings
.LineThickness
,
112 2 * Settings
.Keepaway
, Rat
->Flags
);
115 AddObjectToCreateUndoList (LINE_TYPE
, CURRENT
, new, new);
116 DrawLine (CURRENT
, new, 0);
118 MoveObjectToRemoveUndoList (RATLINE_TYPE
, Rat
, Rat
, Rat
);
123 /* ---------------------------------------------------------------------------
124 * inserts a point into a line
127 InsertPointIntoLine (LayerTypePtr Layer
, LineTypePtr Line
)
132 if (((Line
->Point1
.X
== InsertX
) && (Line
->Point1
.Y
== InsertY
)) ||
133 ((Line
->Point2
.X
== InsertX
) && (Line
->Point2
.Y
== InsertY
)))
137 AddObjectToMoveUndoList (LINEPOINT_TYPE
, Layer
, Line
, &Line
->Point2
,
138 InsertX
- X
, InsertY
- Y
);
140 r_delete_entry (Layer
->line_tree
, (BoxTypePtr
) Line
);
141 Line
->Point2
.X
= InsertX
;
142 Line
->Point2
.Y
= InsertY
;
143 SetLineBoundingBox (Line
);
144 r_insert_entry (Layer
->line_tree
, (BoxTypePtr
) Line
, 0);
145 DrawLine (Layer
, Line
, 0);
146 /* we must create after playing with Line since creation may
147 * invalidate the line pointer
149 if ((line
= CreateDrawnLineOnLayer (Layer
, InsertX
, InsertY
,
151 Line
->Thickness
, Line
->Clearance
,
154 AddObjectToCreateUndoList (LINE_TYPE
, Layer
, line
, line
);
155 DrawLine (Layer
, line
, 0);
156 /* creation call adds it to the rtree */
162 /* ---------------------------------------------------------------------------
163 * inserts a point into a polygon
166 InsertPointIntoPolygon (LayerTypePtr Layer
, PolygonTypePtr Polygon
)
175 * first make sure adding the point is sensible
178 line
.Point1
= Polygon
->Points
[prev_contour_point (Polygon
, InsertAt
)];
179 line
.Point2
= Polygon
->Points
[InsertAt
];
180 if (IsPointOnLine ((float) InsertX
, (float) InsertY
, 0.0, &line
))
184 * second, shift the points up to make room for the new point
186 ErasePolygon (Polygon
);
187 r_delete_entry (Layer
->polygon_tree
, (BoxTypePtr
) Polygon
);
188 save
= *CreateNewPointInPolygon (Polygon
, InsertX
, InsertY
);
189 for (n
= Polygon
->PointN
- 1; n
> InsertAt
; n
--)
190 Polygon
->Points
[n
] = Polygon
->Points
[n
- 1];
192 /* Shift up indices of any holes */
193 for (n
= 0; n
< Polygon
->HoleIndexN
; n
++)
194 if (Polygon
->HoleIndex
[n
] > InsertAt
||
195 (InsertLast
&& Polygon
->HoleIndex
[n
] == InsertAt
))
196 Polygon
->HoleIndex
[n
]++;
198 Polygon
->Points
[InsertAt
] = save
;
199 SetChangedFlag (true);
200 AddObjectToInsertPointUndoList (POLYGONPOINT_TYPE
, Layer
, Polygon
,
201 &Polygon
->Points
[InsertAt
]);
203 SetPolygonBoundingBox (Polygon
);
204 r_insert_entry (Layer
->polygon_tree
, (BoxType
*) Polygon
, 0);
205 InitClip (PCB
->Data
, Layer
, Polygon
);
206 if (Forcible
|| !RemoveExcessPolygonPoints (Layer
, Polygon
))
208 DrawPolygon (Layer
, Polygon
, 0);
211 return (&Polygon
->Points
[InsertAt
]);
214 /* ---------------------------------------------------------------------------
215 * inserts point into objects
218 InsertPointIntoObject (int Type
, void *Ptr1
, void *Ptr2
, Cardinal
* Ptr3
,
219 LocationType DX
, LocationType DY
, bool Force
,
228 InsertLast
= insert_last
;
231 /* the operation insert the points to the undo-list */
232 ptr
= ObjectOperation (&InsertFunctions
, Type
, Ptr1
, Ptr2
, Ptr3
);
234 IncrementUndoSerialNumber ();
238 /* ---------------------------------------------------------------------------
239 * adjusts the insert point to make 45 degree lines as necessary
242 AdjustInsertPoint (void)
244 static PointType InsertedPoint
;
246 LocationType x
, y
, dx
, dy
, m1
, m2
;
247 LineTypePtr line
= (LineTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
249 if (Crosshair
.AttachedObject
.State
== STATE_FIRST
)
251 Crosshair
.AttachedObject
.Ptr3
= &InsertedPoint
;
252 if (gui
->shift_is_pressed ())
254 AttachedLineType myline
;
255 dx
= Crosshair
.X
- line
->Point1
.X
;
256 dy
= Crosshair
.Y
- line
->Point1
.Y
;
257 m
= dx
* dx
+ dy
* dy
;
258 dx
= Crosshair
.X
- line
->Point2
.X
;
259 dy
= Crosshair
.Y
- line
->Point2
.Y
;
260 /* only force 45 degree for nearest point */
261 if (m
< (dx
* dx
+ dy
* dy
))
262 myline
.Point1
= myline
.Point2
= line
->Point1
;
264 myline
.Point1
= myline
.Point2
= line
->Point2
;
265 FortyFiveLine (&myline
);
266 InsertedPoint
.X
= myline
.Point2
.X
;
267 InsertedPoint
.Y
= myline
.Point2
.Y
;
268 return &InsertedPoint
;
270 if (TEST_FLAG (ALLDIRECTIONFLAG
, PCB
))
272 InsertedPoint
.X
= Crosshair
.X
;
273 InsertedPoint
.Y
= Crosshair
.Y
;
274 return &InsertedPoint
;
276 dx
= Crosshair
.X
- line
->Point1
.X
;
277 dy
= Crosshair
.Y
- line
->Point1
.Y
;
279 m1
= 2; /* 2 signals infinite slope */
282 m
= (float) dy
/ (float) dx
;
284 if (m
> TAN_30_DEGREE
)
285 m1
= (m
> TAN_60_DEGREE
) ? 2 : 1;
286 else if (m
< -TAN_30_DEGREE
)
287 m1
= (m
< -TAN_60_DEGREE
) ? 2 : -1;
289 dx
= Crosshair
.X
- line
->Point2
.X
;
290 dy
= Crosshair
.Y
- line
->Point2
.Y
;
292 m2
= 2; /* 2 signals infinite slope */
295 m
= (float) dy
/ (float) dx
;
297 if (m
> TAN_30_DEGREE
)
298 m2
= (m
> TAN_60_DEGREE
) ? 2 : 1;
299 else if (m
< -TAN_30_DEGREE
)
300 m2
= (m
< -TAN_60_DEGREE
) ? 2 : -1;
304 InsertedPoint
.X
= line
->Point1
.X
;
305 InsertedPoint
.Y
= line
->Point1
.Y
;
306 return &InsertedPoint
;
311 y
= line
->Point2
.Y
+ m2
* (line
->Point1
.X
- line
->Point2
.X
);
316 y
= line
->Point1
.Y
+ m1
* (line
->Point2
.X
- line
->Point1
.X
);
320 x
= (line
->Point2
.Y
- line
->Point1
.Y
+ m1
* line
->Point1
.X
321 - m2
* line
->Point2
.X
) / (m1
- m2
);
322 y
= (m1
* line
->Point2
.Y
- m1
* m2
* line
->Point2
.X
323 - m2
* line
->Point1
.Y
+ m1
* m2
* line
->Point1
.X
) / (m1
- m2
);
327 return &InsertedPoint
;