;;; -*- Mode: Lisp; Package: DESIGN; Syntax: Ansi-common-lisp -*-

;; x-in-y

(defmethod x-in-y (x (y use-space))
  ; figure out better way to figure out if use segment or region
  (x-in-y x (territory y)))

(defmethod x-in-y ((x list) (y geometric-form))
  ;; x is list of edges
  (loop for edge in x
	   unless (x-in-y edge y)
	     do (return nil)
	finally (return t)))

(defmethod x-in-y ((x geometric-form) (y geometric-form))
  (x-in-y (edges x) y))

#+ignore
(defmethod x-in-y ((x geometric-form) (y territory))
  (multiple-value-bind (xx-min xy-min xx-max xy-max)
      (bounding-rectangle x)
    (multiple-value-bind (yx-min yy-min yx-max yy-max)
	(bounding-rectangle y)
      (and (<= yx-min xx-min xx-max yx-max)
	   (<= yy-min xy-min xy-max yy-max)))))

(defmethod x-in-y ((x point) (y geometric-form))
  (let ((point-x (point-x x))
	(point-y (point-y x)))
    (multiple-value-bind (x-min y-min x-max y-max)
	(bounding-rectangle y)
      (and (<= x-min point-x x-max)
	   (<= y-min point-y y-max)))))

(defmethod x-in-y ((x basic-edge) (y geometric-form))
  (let* ((point1 (endpoint1 x))
	 (point2 (endpoint2 x))
	 (point1-x (point-x point1))
	 (point1-y (point-y point1))
	 (point2-x (point-x point2))
	 (point2-y (point-y point2)))
    (multiple-value-bind (x-min y-min x-max y-max)
	(bounding-rectangle y)
      (and (<= x-min point1-x x-max)
	   (<= x-min point2-x x-max)
	   (<= y-min point1-y y-max)
	   (<= y-min point2-y y-max)))))


;; Territories are interior if they are inside the exterior perimeter (interiorp ivar).
;; Edges are completely-interior if they are not part of an exterior territory.
;; Territories are completely-interior if all their edges are completely-interior.

(defmethod interior-territories ((model territory-model))
  (remove-if-not #'interiorp (territories model)))


(defmethod completely-interiorp ((edge edge) &optional (tmodel (default-territory-model edge)))
  ;; find territories sharing this edge and see if all are interior
  ;; or if no territories share, is edge in (using x-in-y) an interior territory
  ;; if one space shares, assume shared with exterior
  (let ((territories (territories-for-model edge tmodel)))
    (cond ((= (length territories) 1) nil)
	  ((>= (length territories) 2)
	   (every #'interiorp territories))
	  (t (some #'(lambda (x) (and x (not (member edge (edges x)))
				      (x-in-y edge x)))
		   (remove-if-not #'interiorp (territories tmodel)))))))

(defmethod completely-interiorp ((x geometric-form)
				 &optional (tmodel (territory-model x)))
  (every #'(lambda(x) (completely-interiorp x tmodel)) (edges x)))



