All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
polyblk.cpp
Go to the documentation of this file.
1 /**********************************************************************
2  * File: polyblk.c (Formerly poly_block.c)
3  * Description: Polygonal blocks
4  * Author: Sheelagh Lloyd?
5  * Created:
6  *
7  * (C) Copyright 1993, Hewlett-Packard Ltd.
8  ** Licensed under the Apache License, Version 2.0 (the "License");
9  ** you may not use this file except in compliance with the License.
10  ** You may obtain a copy of the License at
11  ** http://www.apache.org/licenses/LICENSE-2.0
12  ** Unless required by applicable law or agreed to in writing, software
13  ** distributed under the License is distributed on an "AS IS" BASIS,
14  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  ** See the License for the specific language governing permissions and
16  ** limitations under the License.
17  *
18  **********************************************************************/
19 
20 #include <ctype.h>
21 #include <math.h>
22 #include <stdio.h>
23 #include "elst.h"
24 #include "polyblk.h"
25 
26 // Include automatically generated configuration file if running autoconf.
27 #ifdef HAVE_CONFIG_H
28 #include "config_auto.h"
29 #endif
30 
31 #define PBLOCK_LABEL_SIZE 150
32 #define INTERSECTING MAX_INT16
33 
34 int lessthan(const void *first, const void *second);
35 
36 POLY_BLOCK::POLY_BLOCK(ICOORDELT_LIST *points, PolyBlockType t) {
37  ICOORDELT_IT v = &vertices;
38 
39  vertices.clear();
40  v.move_to_first();
41  v.add_list_before(points);
42  compute_bb();
43  type = t;
44 }
45 
46 // Initialize from box coordinates.
48  vertices.clear();
49  ICOORDELT_IT v = &vertices;
50  v.move_to_first();
51  v.add_to_end(new ICOORDELT(box.left(), box.top()));
52  v.add_to_end(new ICOORDELT(box.left(), box.bottom()));
53  v.add_to_end(new ICOORDELT(box.right(), box.bottom()));
54  v.add_to_end(new ICOORDELT(box.right(), box.top()));
55  compute_bb();
56  type = t;
57 }
58 
65 void POLY_BLOCK::compute_bb() { //constructor
66  ICOORD ibl, itr; //integer bb
67  ICOORD botleft; //bounding box
68  ICOORD topright;
69  ICOORD pos; //current pos;
70  ICOORDELT_IT pts = &vertices; //iterator
71 
72  botleft = *pts.data ();
73  topright = botleft;
74  do {
75  pos = *pts.data ();
76  if (pos.x () < botleft.x ())
77  //get bounding box
78  botleft = ICOORD (pos.x (), botleft.y ());
79  if (pos.y () < botleft.y ())
80  botleft = ICOORD (botleft.x (), pos.y ());
81  if (pos.x () > topright.x ())
82  topright = ICOORD (pos.x (), topright.y ());
83  if (pos.y () > topright.y ())
84  topright = ICOORD (topright.x (), pos.y ());
85  pts.forward ();
86  }
87  while (!pts.at_first ());
88  ibl = ICOORD (botleft.x (), botleft.y ());
89  itr = ICOORD (topright.x (), topright.y ());
90  box = TBOX (ibl, itr);
91 }
92 
93 
102  inT16 count; //winding count
103  ICOORD pt; //current point
104  ICOORD vec; //point to current point
105  ICOORD vvec; //current point to next point
106  inT32 cross; //cross product
107  ICOORDELT_IT it = &vertices; //iterator
108 
109  count = 0;
110  do {
111  pt = *it.data ();
112  vec = pt - point;
113  vvec = *it.data_relative (1) - pt;
114  //crossing the line
115  if (vec.y () <= 0 && vec.y () + vvec.y () > 0) {
116  cross = vec * vvec; //cross product
117  if (cross > 0)
118  count++; //crossing right half
119  else if (cross == 0)
120  return INTERSECTING; //going through point
121  }
122  else if (vec.y () > 0 && vec.y () + vvec.y () <= 0) {
123  cross = vec * vvec;
124  if (cross < 0)
125  count--; //crossing back
126  else if (cross == 0)
127  return INTERSECTING; //illegal
128  }
129  else if (vec.y () == 0 && vec.x () == 0)
130  return INTERSECTING;
131  it.forward ();
132  }
133  while (!it.at_first ());
134  return count; //winding number
135 }
136 
137 
140  inT16 count; // winding count
141  ICOORDELT_IT it = &vertices; // iterator
142  ICOORD vertex;
143 
144  if (!box.overlap (*(other->bounding_box ())))
145  return false; // can't be contained
146 
147  /* check that no vertex of this is inside other */
148 
149  do {
150  vertex = *it.data ();
151  // get winding number
152  count = other->winding_number (vertex);
153  if (count != INTERSECTING)
154  if (count != 0)
155  return false;
156  it.forward ();
157  }
158  while (!it.at_first ());
159 
160  /* check that all vertices of other are inside this */
161 
162  //switch lists
163  it.set_to_list (other->points ());
164  do {
165  vertex = *it.data ();
166  //try other way round
167  count = winding_number (vertex);
168  if (count != INTERSECTING)
169  if (count == 0)
170  return false;
171  it.forward ();
172  }
173  while (!it.at_first ());
174  return true;
175 }
176 
177 
185 void POLY_BLOCK::rotate(FCOORD rotation) {
186  FCOORD pos; //current pos;
187  ICOORDELT *pt; //current point
188  ICOORDELT_IT pts = &vertices; //iterator
189 
190  do {
191  pt = pts.data ();
192  pos.set_x (pt->x ());
193  pos.set_y (pt->y ());
194  pos.rotate (rotation);
195  pt->set_x ((inT16) (floor (pos.x () + 0.5)));
196  pt->set_y ((inT16) (floor (pos.y () + 0.5)));
197  pts.forward ();
198  }
199  while (!pts.at_first ());
200  compute_bb();
201 }
202 
210  ICOORDELT *pt; // current point
211  ICOORDELT_IT pts = &vertices; // Iterator.
212 
213  do {
214  pt = pts.data();
215  pt->set_x(-pt->x());
216  pts.forward();
217  }
218  while (!pts.at_first());
219  compute_bb();
220 }
221 
222 
231  ICOORDELT *pt; //current point
232  ICOORDELT_IT pts = &vertices; //iterator
233 
234  do {
235  pt = pts.data ();
236  *pt += shift;
237  pts.forward ();
238  }
239  while (!pts.at_first ());
240  compute_bb();
241 }
242 
243 
244 #ifndef GRAPHICS_DISABLED
245 void POLY_BLOCK::plot(ScrollView* window, inT32 num) {
246  ICOORDELT_IT v = &vertices;
247 
248  window->Pen(ColorForPolyBlockType(type));
249 
250  v.move_to_first ();
251 
252  if (num > 0) {
253  window->TextAttributes("Times", 80, false, false, false);
254  char temp_buff[34];
255  #if defined(__UNIX__) || defined(MINGW)
256  sprintf(temp_buff, INT32FORMAT, num);
257  #else
258  ltoa (num, temp_buff, 10);
259  #endif
260  window->Text(v.data ()->x (), v.data ()->y (), temp_buff);
261  }
262 
263  window->SetCursor(v.data ()->x (), v.data ()->y ());
264  for (v.mark_cycle_pt (); !v.cycled_list (); v.forward ()) {
265  window->DrawTo(v.data ()->x (), v.data ()->y ());
266  }
267  v.move_to_first ();
268  window->DrawTo(v.data ()->x (), v.data ()->y ());
269 }
270 
271 
273  inT16 y;
274  inT16 width;
275  PB_LINE_IT *lines;
276  ICOORDELT_LIST *segments;
277  ICOORDELT_IT s_it;
278 
279  lines = new PB_LINE_IT (this);
280  window->Pen(colour);
281 
282  for (y = this->bounding_box ()->bottom ();
283  y <= this->bounding_box ()->top (); y++) {
284  segments = lines->get_line (y);
285  if (!segments->empty ()) {
286  s_it.set_to_list (segments);
287  for (s_it.mark_cycle_pt (); !s_it.cycled_list (); s_it.forward ()) {
288  // Note different use of ICOORDELT, x coord is x coord of pixel
289  // at the start of line segment, y coord is length of line segment
290  // Last pixel is start pixel + length.
291  width = s_it.data ()->y ();
292  window->SetCursor(s_it.data ()->x (), y);
293  window->DrawTo(s_it.data ()->x () + (float) width, y);
294  }
295  }
296  }
297 }
298 #endif
299 
300 
303  inT16 count; // winding count
304  ICOORDELT_IT it = &vertices; // iterator
305  ICOORD vertex;
306 
307  if (!box.overlap(*(other->bounding_box())))
308  return false; // can't be any overlap.
309 
310  /* see if a vertex of this is inside other */
311 
312  do {
313  vertex = *it.data ();
314  // get winding number
315  count = other->winding_number (vertex);
316  if (count != INTERSECTING)
317  if (count != 0)
318  return true;
319  it.forward ();
320  }
321  while (!it.at_first ());
322 
323  /* see if a vertex of other is inside this */
324 
325  // switch lists
326  it.set_to_list (other->points ());
327  do {
328  vertex = *it.data();
329  // try other way round
330  count = winding_number (vertex);
331  if (count != INTERSECTING)
332  if (count != 0)
333  return true;
334  it.forward ();
335  }
336  while (!it.at_first ());
337  return false;
338 }
339 
340 
341 ICOORDELT_LIST *PB_LINE_IT::get_line(inT16 y) {
342  ICOORDELT_IT v, r;
343  ICOORDELT_LIST *result;
344  ICOORDELT *x, *current, *previous;
345  float fy, fx;
346 
347  fy = (float) (y + 0.5);
348  result = new ICOORDELT_LIST ();
349  r.set_to_list (result);
350  v.set_to_list (block->points ());
351 
352  for (v.mark_cycle_pt (); !v.cycled_list (); v.forward ()) {
353  if (((v.data_relative (-1)->y () > y) && (v.data ()->y () <= y))
354  || ((v.data_relative (-1)->y () <= y) && (v.data ()->y () > y))) {
355  previous = v.data_relative (-1);
356  current = v.data ();
357  fx = (float) (0.5 + previous->x () +
358  (current->x () - previous->x ()) * (fy -
359  previous->y ()) /
360  (current->y () - previous->y ()));
361  x = new ICOORDELT ((inT16) fx, 0);
362  r.add_to_end (x);
363  }
364  }
365 
366  if (!r.empty ()) {
367  r.sort (lessthan);
368  for (r.mark_cycle_pt (); !r.cycled_list (); r.forward ())
369  x = r.data ();
370  for (r.mark_cycle_pt (); !r.cycled_list (); r.forward ()) {
371  r.data ()->set_y (r.data_relative (1)->x () - r.data ()->x ());
372  r.forward ();
373  delete (r.extract ());
374  }
375  }
376 
377  return result;
378 }
379 
380 
381 int lessthan(const void *first, const void *second) {
382  ICOORDELT *p1 = (*(ICOORDELT **) first);
383  ICOORDELT *p2 = (*(ICOORDELT **) second);
384 
385  if (p1->x () < p2->x ())
386  return (-1);
387  else if (p1->x () > p2->x ())
388  return (1);
389  else
390  return (0);
391 }
392 
393 #ifndef GRAPHICS_DISABLED
396  // Keep kPBColors in sync with PolyBlockType.
397  const ScrollView::Color kPBColors[PT_COUNT] = {
398  ScrollView::WHITE, // Type is not yet known. Keep as the 1st element.
399  ScrollView::BLUE, // Text that lives inside a column.
400  ScrollView::CYAN, // Text that spans more than one column.
401  ScrollView::MEDIUM_BLUE, // Text that is in a cross-column pull-out region.
402  ScrollView::AQUAMARINE, // Partition belonging to an equation region.
403  ScrollView::SKY_BLUE, // Partition belonging to an inline equation region.
404  ScrollView::MAGENTA, // Partition belonging to a table region.
405  ScrollView::GREEN, // Text-line runs vertically.
406  ScrollView::LIGHT_BLUE, // Text that belongs to an image.
407  ScrollView::RED, // Image that lives inside a column.
408  ScrollView::YELLOW, // Image that spans more than one column.
409  ScrollView::ORANGE, // Image in a cross-column pull-out region.
410  ScrollView::BROWN, // Horizontal Line.
411  ScrollView::DARK_GREEN, // Vertical Line.
412  ScrollView::GREY // Lies outside of any column.
413  };
414  if (type >= 0 && type < PT_COUNT) {
415  return kPBColors[type];
416  }
417  return ScrollView::WHITE;
418 }
419 #endif // GRAPHICS_DISABLED
void set_x(inT16 xin)
rewrite function
Definition: points.h:61
void Pen(Color color)
Definition: scrollview.cpp:726
int lessthan(const void *first, const void *second)
Definition: polyblk.cpp:381
void reflect_in_y_axis()
Definition: polyblk.cpp:209
float x() const
Definition: points.h:209
void rotate(FCOORD rotation)
Definition: polyblk.cpp:185
static ScrollView::Color ColorForPolyBlockType(PolyBlockType type)
Returns a color to draw the given type.
Definition: polyblk.cpp:395
void Text(int x, int y, const char *mystring)
Definition: scrollview.cpp:658
void DrawTo(int x, int y)
Definition: scrollview.cpp:531
bool contains(POLY_BLOCK *other)
Definition: polyblk.cpp:139
void rotate(const FCOORD vec)
Definition: ipoints.h:471
#define INT32FORMAT
Definition: host.h:115
void TextAttributes(const char *font, int pixel_size, bool bold, bool italic, bool underlined)
Definition: scrollview.cpp:641
void compute_bb()
Definition: polyblk.cpp:65
inT16 right() const
Definition: rect.h:75
Definition: capi.h:79
ICOORDELT_LIST * get_line(inT16 y)
Definition: polyblk.cpp:341
bool overlap(POLY_BLOCK *other)
Definition: polyblk.cpp:302
void move(ICOORD shift)
Definition: polyblk.cpp:230
inT16 y() const
access_function
Definition: points.h:56
inT16 left() const
Definition: rect.h:68
void set_x(float xin)
rewrite function
Definition: points.h:216
void SetCursor(int x, int y)
Definition: scrollview.cpp:525
TBOX * bounding_box()
Definition: polyblk.h:38
void set_y(float yin)
rewrite function
Definition: points.h:220
ICOORDELT_LIST * points()
Definition: polyblk.h:42
void fill(ScrollView *window, ScrollView::Color colour)
Definition: polyblk.cpp:272
integer coordinate
Definition: points.h:30
inT16 bottom() const
Definition: rect.h:61
#define INTERSECTING
Definition: polyblk.cpp:32
void set_y(inT16 yin)
rewrite function
Definition: points.h:65
void plot(ScrollView *window, inT32 num)
Definition: polyblk.cpp:245
int count(LIST var_list)
Definition: oldlist.cpp:108
inT16 x() const
access function
Definition: points.h:52
Definition: rect.h:30
float y() const
Definition: points.h:212
POLY_BLOCK()
Definition: polyblk.h:30
PolyBlockType
Definition: publictypes.h:41
inT16 winding_number(const ICOORD &test_pt)
Definition: polyblk.cpp:101
inT16 top() const
Definition: rect.h:54
Definition: points.h:189
bool overlap(const TBOX &box) const
Definition: rect.h:345
short inT16
Definition: host.h:100
int inT32
Definition: host.h:102