; .EnTete "Programmer en Ceyx" "" "Annexe II: Le Plan Carte'sien"
; .Annexe II "Le Plan Carte'sien"
; .Auteur "Jean-Marie Hullot, Bertrand Serlet, Jean Vuillemin"
; .i
; Ce chapitre est un exemple d'utilisation de mode`les non auto-type's
; c'est a` dire de'finis par defmodel, defrecord ... Nous rappelons
; que les Records Ceyx sont imple'mente's comme des arbres e'quilibre's
; de cellules cons.
; 
; Toutes les fonctions de'crites ici sont utilisables sous Ceyx a`
; condition d'avoir charge' le fichier coord.ll de la bibliothe`que
; Ceyx, qui n'est d'ailleurs pas autre chose que ce chapitre:
; .r
; 
; .DebLL 1
; ? (ceyx-load coord)
; = coord.ll
; .FinLL
; .pp
; 
; Nous pre'sentons ici des structures permettant de repre'senter
; des coordonne'es et des rectangles dans le plan carte'sien et
; les proprie'te's se'mantiques e'le'mentaires de ces structures.
; 
; .Section "Les Coordonne'es"

; .ps -2
; .TS
; center box tab (|);
; c s
; c c.
; T{
; .ps +1
; \fBLe Mode`le: Coord\fR
; .ps -1
; T}
;  | 
; ←
; ←
; .T&
; c s
; l l.
; \fBFonction de Cre'ation\fR
; Coord|(x y)
; ←
; .T&
; c s
; l l.
; \fBChamps\fR
; x|number
; y|number
; ←
; .T&
; c s
; l l.
; \fBProprie'te's Se'mantiques\fR
; *|(coord ratio)
; +|(coord dxy)
; +*|(coord homvect)
; -|(coord dxy)
; max|(coord1 coord2)
; min|(coord1 coord2)
; translate|(coord dx dy)
; x|obj
; y|obj
; ←
; .T&
; c s
; l s.
; \fBSous Mode`les\fR
; Dxy
; Ratio
; .TE
; .ps +2

; Nous nous plac/ons dans un repe`re de coordonne'es de type e'cran,
; c'est a` dire que l'axe des x est horizontal de la gauche vers la
; droite et l'axe des y vertical du haut vers le bas. Les \fIcoordonne'es\fR
; sont repre'sente'es par des records a` deux champs:

(defrecord Coord (x~number 0) (y~number 0))

(defmake {Coord} Coord (x y))


; \fBExemples:\fR
; 
; .DebLL 1
; ? (setq c01 (Coord 0 1))
; = (0 . 1)
; ? ({Coord}:x c01)
; = 0
; ? ({Coord}:y c01)
; = 1
; .FinLL
; .pp

; Le min et le max sur les coordonne'es:

(de {Coord}:min (coord1 coord2)
    (Coord (min ({Coord}:x coord1) ({Coord}:x coord2))
           (min ({Coord}:y coord1) ({Coord}:y coord2))))
    
(de {Coord}:max (coord1 coord2)
    (Coord (max ({Coord}:x coord1) ({Coord}:x coord2))
           (max ({Coord}:y coord1) ({Coord}:y coord2))))
    
; \fBExemples:\fR
; 
; .DebLL 1
; ? (setq c1 (Coord 1 3) c2 (Coord 4 2))
; = (4 . 2)
; ? ({Coord}:min c1 c2)
; = (1 . 2)
; ? ({Coord}:max c1 c2)
; = (4 . 3)
; ? c1
; = (1 . 3)
; ? c2
; = (4 . 2)
; .FinLL
; .pp
; 
; Pour translater une coordonne'e de dx, dy:

(de {Coord}:translate (coord dx dy)
    ({Coord}:x coord (+ ({Coord}:x coord) dx))
    ({Coord}:y coord (+ ({Coord}:y coord) dy))
    coord)

; \fBExemples:\fR
; 
; .DebLL 1
; ? ({Coord}:translate c1 7 5)
; = (8 . 8)
; ? c1
; = (8 . 8)
; .FinLL
; .pp
; 
; .bp
; .Section "Les Vecteurs"

; .ps -2
; .TS
; center box tab (|);
; c s
; c c.
; T{
; .ps +1
; \fBLe Mode`le: Vect\fR
; .ps -1
; T}
;  | 
; ←
; ←
; .T&
; c s
; l l.
; \fBFonctions de Cre'ation\fR
; mkvect|(xorg yorg xext yext)
; Vect|(org ext)
; ←
; .T&
; c s
; l l.
; \fBChamps\fR
; org|(Cons ...)
; xorg|number
; yorg|number
; ext|(Cons ...)
; xext|number
; yext|number
; ←
; .T&
; c s
; l l.
; \fBProprie'te's Se'mantiques\fR
; *|(vect ratio)
; +|(vect dxy)
; +*|(vect homvect)
; dx|(vect)
; dy|(vect)
; ext|obj
; null|(vect)
; org|obj
; translate|(vect dx dy)
; xext|obj
; xorg|obj
; yext|obj
; yorg|obj
; ←
; .T&
; c s
; l s.
; \fBSous Mode`le\fR
; HomVect
; .TE
; .ps +2

; Les vecteurs sont repre'sente's par
; un couple de coordonne'es dont l'une est appele'e
; origine et l'autre extre↑mite':

(defrecord Vect org~(Alter Coord x (Field xorg number 0)
                                 y (Field yorg number 0))
                ext~(Alter Coord x (Field xext number 0)
                                 y (Field yext number 0)))


(defmake {Vect} Vect (org ext))
(defmake {Vect} mkvect (xorg yorg xext yext))

; \fBExemples:\fR
; 
; .DebLL 1
; ? (setq vect (Vect c1 c2))
; = ((8 . 8) 4 . 2)
; ? ({Vect}:org vect)
; = (8 . 8)
; ? ({Vect}:xorg vect)
; = 8
; ? ({Vect}:yext vect)
; = 2
; .FinLL
; .pp
; 
; Nous conside`rerons dans la suite que le vecteur est ferme' en son
; origine et ouvert en son extre↑mite', c'est a` dire que son
; extre↑mite' ne lui appartient pas. Ainsi un vecteur est-il vide
; si et seulement si son origine et son extre↑mite' sont
; confondues:

(de {Vect}:null (vect)
    (and (= ({Vect}:xorg vect) ({Vect}:xext vect))
         (= ({Vect}:yorg vect) ({Vect}:yext vect))))

; \fBExemples:\fR
; 
; .DebLL 1
; ? ({Vect}:null vect)
; = ()
; ? ({Vect}:null (Vect (Coord 3 4) (Coord 3 4)))
; = 4
; .FinLL
; .pp
; 
; La diffe'rence des coordonne'es en x et en y:

(de {Vect}:dx (vect)
    (- ({Vect}:xext vect) ({Vect}:xorg vect)))

(de {Vect}:dy (vect)
    (- ({Vect}:yext vect) ({Vect}:yorg vect)))

(cxcp-inline ({Vect}:dx vect))
(cxcp-inline ({Vect}:dy vect))


; \fBExemples:\fR
; 
; .DebLL 1
; ? vect
; = ((8 . 8) 4 . 2)
; ? ({Vect}:dx vect)
; = -4
; ? ({Vect}:dy vect)
; = -6
; .FinLL
; .pp

; Translation d'un vecteur de dx, dy:

(de {Vect}:translate (vect dx dy)
    ({Coord}:translate ({Vect}:org vect) dx dy)
    ({Coord}:translate ({Vect}:ext vect) dx dy)
    vect)

; .bp
; .Section "Les Rectangles"

; .ps -2
; .TS
; center box tab (|);
; c s
; c c.
; T{
; .ps +1
; \fBLe Mode`le: Rect\fR
; .ps -1
; T}
;  | 
; ←
; ←
; .T&
; c s
; l l.
; \fBFonctions de Cre'ation\fR
; mkrect|(x y w h)
; Rect|(coord1 coord2)
; ←
; .T&
; c s
; l l.
; \fBChamps\fR
; org|(Cons ...)
; xorg|number
; yorg|number
; ext|(Cons ...)
; xext|number
; yext|number
; ←
; .T&
; c s
; l l.
; \fBProprie'te's Se'mantiques\fR
; *|(vect ratio)
; +|(vect dxy)
; +*|(vect homvect)
; <-Rect|(rect1 rect2)
; <-inter|(rect1 rect2)
; contains-coord|(rect coord)
; contains-rect|(rect1 rect2)
; ext|obj
; height|(vect)
; inter|(rect1 rect2)
; inter?|(rect1 rect2)
; mkinter|(rect1 rect2)
; null|(vect)
; org|obj
; translate|(vect dx dy)
; union|(rect1 rect2)
; width|(vect)
; xext|obj
; xorg|obj
; yext|obj
; yorg|obj
; ←
; .T&
; c s
; l s.
; \fBSous Mode`le\fR
; ClipRect
; .TE
; .ps +2

; Les \fIrectangles\fR sont de'termine's par leur coin supe'rieur gauche
; et leur coin infe'rieur droit. Ils sont imple'mente's 
; de la me↑me manie`re que des \fBVect\fR.

(defmodel Rect Vect)

(de Rect (coord1 coord2)
    (Vect ({Coord}:min coord1 coord2) ({Coord}:max coord1 coord2)))

(defmake {Rect} Rect)

(de mkrect (x y w h)
    (mkvect x y (+ x w) (+ y h)))

(defmake {Rect} mkrect)

(defaccess Rect)

; \fBExemples:\fR
; 
; .DebLL 1
; ? (setq rect1 (Rect (Coord 0 0) (Coord 10 10)))
; = ((0 . 0) 10 . 10)
; ? (setq rect2 (Rect (Coord 20 20) (Coord 10 10)))
; = ((10 . 10) 20 . 20)
; .FinLL
; .pp
; Quelques synonymes:

(synonymq {Rect}:null {Vect}:null)
(synonymq {Rect}:width {Vect}:dx)
(synonymq {Rect}:height {Vect}:dy)
(synonymq {Rect}:translate {Vect}:translate)


; \fBExemples:\fR
; 
; .DebLL 1
; ? ({Rect}:org rect1)
; = (0 . 0)
; ? ({Rect}:width rect1)
; = 10
; ? ({Rect}:height rect2)
; = 10
; ? rect2
; = ((10 . 10) 20 . 20)
; ? ({Rect}:+ rect2 (Coord 1 1))
; = ((11 . 11) 21 . 21)
; .FinLL
; .pp
; Pour de'terminer si un \fBRect\fR contient une \fBCoord\fR:

(de {Rect}:contains-coord (rect coord)
    (not
     (or (< ({Coord}:x coord) ({Rect}:xorg rect))
         (>= ({Coord}:x coord) ({Rect}:xext rect))
         (< ({Coord}:y coord) ({Rect}:yorg rect))
         (>= ({Coord}:y coord) ({Rect}:yext rect)))))

(cxcp-inline ({Rect}:contains-coord rect coord))

; \fBExemples:\fR
; 
; .DebLL 1
; ? rect1
; = ((0 . 0) 10 . 10)
; ? ({Rect}:contains-coord rect1 (Coord 0 0))
; = t
; ? ({Rect}:contains-coord rect1 (Coord 5 5))
; = t
; ? ({Rect}:contains-coord rect1 (Coord 30 40))
; = ()
; ? ({Rect}:contains-coord rect1 (Coord 10 10))
; = ()
; ? ({Rect}:contains-coord rect1 (Coord 3 10))
; = ()
; .FinLL
; .pp
; Pour de'terminer si un \fBRect\fR en contient un autre:

(de {Rect}:contains-rect (rect1 rect2)
    (and
      ({Rect}:contains-coord rect1 ({Rect}:org rect2))
      ({Rect}:contains-coord rect1 ({Coord}:+ (Coord -1 -1)
                                              ({Rect}:ext rect2)))))

(cxcp-inline ({Rect}:contains-rect rect1 rect2))

; \fBExemples:\fR
; 
; .DebLL 1
; ? rect1
; = ((0 . 0) 10 . 10)
; ? rect2
; = ((6 . 6) 16 . 16)
; ? ({Rect}:contains-rect rect1 rect2)
; = ()
; ? ({Rect}:contains-rect rect1 (Rect (Coord 3 3) (Coord 10 10)))
; = t
; .FinLL
; .pp
; Rame`ne en valeur le rectangle enveloppant de deux rectangles:

(de {Rect}:union (rect1 rect2)
    (Rect 
        ({Coord}:min ({Rect}:org rect1) ({Rect}:org rect2))
        ({Coord}:max ({Rect}:ext rect1) ({Rect}:ext rect2))))

; Rame`ne nil ou le rectangle intersection de deux rectangles.

(de {Rect}:inter (rect1 rect2)
   (if ({Rect}:inter? rect1 rect2)
    ({Rect}:mkinter rect1 rect2)
    ()))

(de {Rect}:inter? (rect1 rect2)
   (and (< (max ({Rect}:xorg rect1) ({Rect}:xorg rect2))
           (min ({Rect}:xext rect1) ({Rect}:xext rect2)))
        (< (max ({Rect}:yorg rect1) ({Rect}:yorg rect2))
           (min ({Rect}:yext rect1) ({Rect}:yext rect2)))))

(de {Rect}:mkinter (rect1 rect2)
    (Rect
       ({Coord}:max ({Rect}:org rect1) ({Rect}:org rect2))
       ({Coord}:min ({Rect}:ext rect1) ({Rect}:ext rect2))))

(cxcp-inline ({Rect}:inter? rect1 rect2))
(cxcp-inline ({Rect}:mkinter rect1 rect2))

; \fBExemples\fR:
; 
; .DebLL 1
; ? rect1
; = ((0 . 0) 10 . 10)
; ? rect2
; = ((11 . 11) 21 . 21)
; ? ({Rect}:union rect1 rect2)
; = ((0 . 0) 21 . 21)
; ? ({Rect}:inter? rect1 rect2)
; = ()
; ? ({Rect}:translate rect2 -5 -5)
; = ((-5 . -5) 16 . 16)
; ? rect2
; = ((6 . 6) 16 . 16)
; ? ({Rect}:inter rect1 rect2)
; = ((6 . 6) 10 . 10)
; .FinLL
; .pp

; Quelques ope'rations de modification en place:

(de {Rect}:<-Rect (rect1 rect2)
    ({Rect}:xorg rect1 ({Rect}:xorg rect2))
    ({Rect}:yorg rect1 ({Rect}:yorg rect2))
    ({Rect}:xext rect1 ({Rect}:xext rect2))
    ({Rect}:yext rect1 ({Rect}:yext rect2))
    rect1)

(cxcp-inline ({Rect}:<-Rect rect1 rect2))

(de {Rect}:<-inter (rect1 rect2)
    (cond
       ((null ({Rect}:inter? rect1 rect2))
        ({Rect}:xext rect1 ({Rect}:xorg rect1))
        ({Rect}:yext rect1 ({Rect}:yorg rect1))
        rect1)
       (t ({Rect}:xorg rect1
                (max ({Rect}:xorg rect1) ({Rect}:xorg rect2)))
          ({Rect}:yorg rect1
                (max ({Rect}:yorg rect1) ({Rect}:yorg rect2)))
          ({Rect}:xext rect1
                (min ({Rect}:xext rect1) ({Rect}:xext rect2)))
          ({Rect}:yext rect1
                (min ({Rect}:yext rect1) ({Rect}:yext rect2)))
          rect1)))


; Les rectangles de clip, utilise's surtout pour inclure dans d'autres
; structures par (Include {ClipRect}).

; .ps -2
; .TS
; center box tab (|);
; c s
; c c.
; T{
; .ps +1
; \fBLe Mode`le: #:Rect:ClipRect\fR
; .ps -1
; T}
;  | 
; ←
; ←
; .T&
; c s.
; T{
; \fBAbre'viation: \fRClipRect.
; T}
; ←
; .T&
; c s
; l l.
; \fBChamps\fR
; cliporg|(Cons ...)
; clipxorg|number
; clipyorg|number
; clipext|(Cons ...)
; clipxext|number
; clipyext|number
; .TE
; .ps +2


(defmodel ({Rect}:ClipRect ClipRect)
          (Cons
             (Field cliporg (Cons
                              (Field clipxorg number 0)
                              (Field clipyorg number 0)))
             (Field clipext (Cons
                              (Field clipxext number 0)
                              (Field clipyext number 0)))))

; .Section "Transformations"
; .SSection "De'finition"
; Pour voir une coordonne'e comme une translation:

; .ps -2
; .TS
; center box tab (|);
; c s
; c c.
; T{
; .ps +1
; \fBLe Mode`le: #:Coord:Dxy\fR
; .ps -1
; T}
;  | 
; ←
; ←
; .T&
; c s.
; T{
; \fBAbre'viation: \fRDxy.
; T}
; ←
; .T&
; c s
; l l.
; \fBFonction de Cre'ation\fR
; Dxy|(dx dy)
; ←
; .T&
; c s
; l l.
; \fBChamps\fR
; dx|number
; dy|number
; ←
; .T&
; c s
; l l.
; \fBProprie'te's Se'mantiques\fR
; dx|obj
; dy|obj
; .TE
; .ps +2


(defmodel ({Coord}:Dxy Dxy)
          (Alter Coord
                 x (Field dx number 0)
                 y (Field dy number 0)))

(defaccess {Dxy})
(defmake {Dxy} Dxy (dx dy))

; Pour voir une coordonne'e comme une homothe'tie:

; .ps -2
; .TS
; center box tab (|);
; c s
; c c.
; T{
; .ps +1
; \fBLe Mode`le: #:Coord:Ratio\fR
; .ps -1
; T}
;  | 
; ←
; ←
; .T&
; c s.
; T{
; \fBAbre'viation: \fRRatio.
; T}
; ←
; .T&
; c s
; l l.
; \fBFonction de Cre'ation\fR
; Ratio|(ratiox ratioy)
; ←
; .T&
; c s
; l l.
; \fBChamps\fR
; ratiox|number
; ratioy|number
; ←
; .T&
; c s
; l l.
; \fBProprie'te's Se'mantiques\fR
; ratiox|obj
; ratioy|obj
; .TE
; .ps +2


(defmodel ({Coord}:Ratio Ratio)
          (Alter Coord
                 x (Field ratiox number 1)
                 y (Field ratioy number 1)))

(defaccess {Ratio})
(defmake {Ratio} Ratio (ratiox ratioy))

; Pour voir un vecteur comme la composition d'une translation
; et d'une homothe'tie:

; .ps -2
; .TS
; center box tab (|);
; c s
; c c.
; T{
; .ps +1
; \fBLe Mode`le: #:Vect:HomVect\fR
; .ps -1
; T}
;  | 
; ←
; ←
; .T&
; c s.
; T{
; \fBAbre'viation: \fRHomVect.
; T}
; ←
; .T&
; c s
; l l.
; \fBFonction de Cre'ation\fR
; HomVect|(dxy ratio)
; ←
; .T&
; c s
; l l.
; \fBChamps\fR
; dxy|(Cons ...)
; dx|number
; dy|number
; ratio|(Cons ...)
; ratiox|number
; ratioy|number
; ←
; .T&
; c s
; l l.
; \fBProprie'te's Se'mantiques\fR
; dx|obj
; dxy|obj
; dy|obj
; ratio|obj
; ratiox|obj
; ratioy|obj
; .TE
; .ps +2

(defmodel ({Vect}:HomVect HomVect)
          (Alter Vect
                 org (Field dxy (Include {Dxy}))
                 ext (Field ratio (Include {Ratio}))))

(defaccess {HomVect})
(defmake {HomVect} HomVect (dxy ratio))

; .SSection "Application des Transformations"

(de {Coord}:+ (coord dxy) 
    ({Coord}:x coord (+ ({Coord}:x coord) ({Dxy}:dx dxy)))
    ({Coord}:y coord (+ ({Coord}:y coord) ({Dxy}:dy dxy)))
    coord)


(de {Coord}:- (coord dxy) 
    ({Coord}:x coord (- ({Coord}:x coord) ({Dxy}:dx dxy)))
    ({Coord}:y coord (- ({Coord}:y coord) ({Dxy}:dy dxy)))
    coord)

(de {Coord}:* (coord ratio) 
    ({Coord}:x coord (* ({Coord}:x coord) ({Ratio}:ratiox ratio)))
    ({Coord}:y coord (* ({Coord}:y coord) ({Ratio}:ratioy ratio)))
    coord)

(de {Coord}:+* (coord homvect)
    ({Coord}:+ coord ({HomVect}:dxy homvect))
    ({Coord}:* coord ({HomVect}:ratio homvect))
    coord)

(de {Vect}:+ (vect dxy)
    ({Coord}:+ ({Vect}:org vect) dxy)
    ({Coord}:+ ({Vect}:ext vect) dxy)
    vect)

(de {Vect}:* (vect ratio)
    ({Coord}:* ({Vect}:org vect) ratio)
    ({Coord}:* ({Vect}:ext vect) ratio)
    vect)

(de {Vect}:+* (vect homvect)
    ({Vect}:+ vect ({HomVect}:dxy homvect))
    ({Vect}:* vect ({HomVect}:ratio homvect))
    vect)

(synonymq {Rect}:+ {Vect}:+)
(synonymq {Rect}:* {Vect}:*)
(synonymq {Rect}:+* {Vect}:+*)