rectangle.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #include "config.h"
  11. #include <label/index.h>
  12. #include <stdbool.h>
  13. #include <stdint.h>
  14. #include <stdio.h>
  15. #include <assert.h>
  16. #include <stdlib.h>
  17. #include <common/arith.h>
  18. #include <label/rectangle.h>
  19. #include <cgraph/cgraph.h>
  20. #include <util/exit.h>
  21. #define Undefined(x) ((x)->boundary[0] > (x)->boundary[NUMDIMS])
  22. /*-----------------------------------------------------------------------------
  23. | Initialize a rectangle to have all 0 coordinates.
  24. -----------------------------------------------------------------------------*/
  25. void InitRect(Rect_t * r)
  26. {
  27. for (size_t i = 0; i < NUMSIDES; i++)
  28. r->boundary[i] = 0;
  29. }
  30. /*-----------------------------------------------------------------------------
  31. | Return a rect whose first low side is higher than its opposite side -
  32. | interpreted as an undefined rect.
  33. -----------------------------------------------------------------------------*/
  34. Rect_t NullRect(void)
  35. {
  36. Rect_t r = {{0}};
  37. r.boundary[0] = 1;
  38. r.boundary[NUMDIMS] = -1;
  39. return r;
  40. }
  41. #ifdef RTDEBUG
  42. /*-----------------------------------------------------------------------------
  43. | Print rectangle lower upper bounds by dimension
  44. -----------------------------------------------------------------------------*/
  45. void PrintRect(Rect_t * r)
  46. {
  47. assert(r);
  48. fprintf(stderr, "rect:");
  49. for (size_t i = 0; i < NUMDIMS; i++)
  50. fprintf(stderr, "\t%d\t%d\n", r->boundary[i],
  51. r->boundary[i + NUMDIMS]);
  52. }
  53. #endif
  54. /*-----------------------------------------------------------------------------
  55. | Calculate the n-dimensional area of a rectangle
  56. -----------------------------------------------------------------------------*/
  57. uint64_t RectArea(const Rect_t *r) {
  58. assert(r);
  59. if (Undefined(r))
  60. return 0;
  61. uint64_t area = 1;
  62. for (size_t i = 0; i < NUMDIMS; i++) {
  63. unsigned int dim = r->boundary[i + NUMDIMS] - r->boundary[i];
  64. if (dim == 0) return 0;
  65. if (UINT64_MAX / dim < area) {
  66. agerrorf("label: area too large for rtree\n");
  67. graphviz_exit(EXIT_FAILURE);
  68. }
  69. area *= dim;
  70. }
  71. return area;
  72. }
  73. /*-----------------------------------------------------------------------------
  74. | Combine two rectangles, make one that includes both.
  75. -----------------------------------------------------------------------------*/
  76. Rect_t CombineRect(const Rect_t *r, const Rect_t *rr) {
  77. Rect_t new;
  78. assert(r && rr);
  79. if (Undefined(r))
  80. return *rr;
  81. if (Undefined(rr))
  82. return *r;
  83. for (size_t i = 0; i < NUMDIMS; i++) {
  84. new.boundary[i] = MIN(r->boundary[i], rr->boundary[i]);
  85. size_t j = i + NUMDIMS;
  86. new.boundary[j] = MAX(r->boundary[j], rr->boundary[j]);
  87. }
  88. return new;
  89. }
  90. /*-----------------------------------------------------------------------------
  91. | Decide whether two rectangles overlap.
  92. -----------------------------------------------------------------------------*/
  93. bool Overlap(const Rect_t *r, const Rect_t *s) {
  94. assert(r && s);
  95. for (size_t i = 0; i < NUMDIMS; i++) {
  96. size_t j = i + NUMDIMS; /* index for high sides */
  97. if (r->boundary[i] > s->boundary[j] || s->boundary[i] > r->boundary[j])
  98. return false;
  99. }
  100. return true;
  101. }