Newsgroup: it.comp.software.cad
Titolo: LISP - Verificare se un punto appartiene ad un segmento

Ciao a tutti,
devo realizzare un funzione in grado di:
- date le coordinate X e Y di tre punti "A" , "B" e "C" verificare se il 
punto "C" si trova all'interno del segmento AB.
Potete aiutarmi?
N.B. il segmento può essere inclinato oppure orizzontale o verticale ma è 
sempre appoggiato a quota "0".

 sempre appoggiato a quota "0".
Prova a buttare giù un ragionamento, pensa a un triangolo...


Prova questa:
;;;;;;;;;;Stabilisce se un punto C è interno ad un segmento A-B oppure no.
(defun C:INT_C (/ pta ptb ptc ptd pte dst_ab dst_ae dst_be dst_ce)
(setq pta(getpoint "\nSelezionare il punto A o fornire le sue coordinate"))
(setq ptb(getpoint "\nSelezionare il punto B o fornire le sue coordinate"))
(setq ptc(getpoint "\nSelezionare il punto C o fornire le sue coordinate"))
(setq ang_ab (angle pta ptb))
(setq ptd (polar ptc (+ ang_ab (/ pi 2)) 10))
(setq pte (inters pta ptb ptc ptd nil))
(setq dst_ab (distance pta ptb)
      dst_ae (distance pta pte)
      dst_be (distance ptb pte)
      dst_ce (distance ptc pte)
)
(if (< dst_ce 0.000001)(setq dst_ce 0))
(if (/= dst_ce 0)
(princ "\nIl punto C non giace né sul segmento A-B né sulla sua retta.")
  (progn
   (if (and (> dst_ae dst_ab)(> dst_be dst_ab))
       (princ "\nIl punto C è esterno ad A-B ma giace sulla sua retta.")
       (princ "\nIl punto C è interno ad A-B.")
   )
 )
)
(princ)
)
(princ "\nIl file INT_C è stato caricato. Digitare INT_C per proseguire.")
(princ)
Saluti
G.B.Francesconi

>
Chiedo scusa ma c'è da fare una rettifica.
Sostituisci la diciannovesima riga con:
(if (or (> dst_ae dst_ab)(> dst_be dst_ab))
cioè al posto di and metti or.
Un errore da parte mia.
Saluti di nuovo
G.B.Francesconi

> "GB Francesconi"
<clip>
Ciao Francesconi,
praticamente si può riassumere in:
; Function: ALE_Point_OnLineP
;
; Version 1.00 - 16/04/2000
;
; Arguments:
;   TstPtn:  test point
;   Pnt001:  first point
;   Pnt002:  second point
;
; Return Values: T or nil
;
; Examples:
;  (ALE_Point_OnLineP '(10 10) '(5 10) '(20 10) 0.0001)
;  ==> T
;
;  (ALE_Point_OnLineP '(10 10) '(20 20) '(30 30) 0.0001)
;  ==> nil
;
(defun ALE_Point_OnLineP (TstPtn Pnt001 Pnt002 FuzFac)
  (and
    (listp TstPtn) (listp Pnt001) (listp Pnt002)
    (numberp FuzFac)
    (equal
      (distance Pnt001 Pnt002)
      (+ (distance Pnt001 TstPtn) (distance Pnt002 TstPtn))
      FuzFac
    )
  )
) 

"Marco_AA" <Marco_AA@Marco_AA.com> ha scritto nel messaggio 
news:4565e782$0$13764$4faf...@reader3.news.tin.it...

Ciao Marco,
eccezionale, come al solito, la tua soluzione.
Ma non c'è partita tra un dilettante e un professionista!
A presto risentirci e magari rivederci
G.B.Francesconi 

Ciao Marco,
grazie, la tua soluzione, pur non avendola compresa funziona alla grande.
Personalmente avevo approntato un LISP che utilizzava l'equazione della 
retta, ma in caso di linee perfettamente orizzontali o verticali dava 
problemi probabilmente a causa di calcoli con virgola mobile.
Ciao.
"Marco_AA" <Marco_AA@Marco_AA.com> ha scritto nel messaggio 
news:4565e782$0$13764$4faf...@reader3.news.tin.it...


 significa che i punti sono allineati
cioè un "triangolo" (tra virgolette) con altezza zero.
--
Marco

Ormai che c'ero ho fatto anche queste, se qualcuno
le vuole testare...
;
; Function: ALE_Point_OnLineP
;
; Version 1.00 - 16/04/2000
; Version 1.01 - 24/11/2006
;
; Arguments:
;   TstPtn:  test point
;   Pnt001:  first point
;   Pnt002:  second point
;   FuzFac:  a real number defining the maximum amount by which 
;            points can differ and still be considered equal
;
; Return Values: T or nil
;
; Examples:
;  (ALE_Point_OnLineP '(10 10) '(10 10) '(20 10) 0.0001)
;  ==> T
;
;  (ALE_Point_OnLineP '(10 10) '(20 20) '(30 30) 0.0001)
;  ==> nil
;
(defun ALE_Point_OnLineP (TstPtn Pnt001 Pnt002 FuzFac)
  (cond
    ( (not
        (and
          (listp TstPtn) (listp Pnt001) (listp Pnt002)
          (numberp FuzFac)
        )
      )
      (alert "Not valid data!")
    )
    ( (equal
        (+ (distance Pnt001 TstPtn) (distance Pnt002 TstPtn))
        (distance Pnt001 Pnt002)
        FuzFac
      )
    )
  )
)
; Function: ALE_Point_OnXLineP
;
; Version 1.00 - 24/11/2006
;
; Arguments:
;   TstPtn:  test point
;   Pnt001:  first point
;   Pnt002:  second point
;   FuzFac:  a real number defining the maximum amount by which 
;            points can differ and still be considered equal
;
; Return Values: T or nil
;
; Examples:
;  (ALE_Point_OnXLineP '(50 10) '(10 10) '(20 10) 0.0001)
;  ==> T
;
;  (ALE_Point_OnXLineP '(50 10) '(10 10) '(20 11) 0.0001)
;  ==> nil
;
(defun ALE_Point_OnXLineP (TstPtn Pnt001 Pnt002 FuzFac)
  (cond
    ( (not
        (and
          (listp TstPtn) (listp Pnt001) (listp Pnt002)
          (numberp FuzFac)
        )
      )
      (alert "Not valid data!")
    )
    ( (or
        (equal (angle Pnt001 Pnt002) (angle TstPtn Pnt002) FuzFac)
        (equal (angle Pnt002 Pnt001) (angle TstPtn Pnt001) FuzFac)
      )
    )
  )
)
; Function: ALE_Point_OnRayP
;
; Version 1.00 - 24/11/2006
;
; Arguments:
;   TstPtn:  test point
;   Pnt001:  first point > start point of ray
;   Pnt002:  second point
;   FuzFac:  a real number defining the maximum amount by which 
;            points can differ and still be considered equal
;
; Return Values: T or nil
;
; Examples:
;  (ALE_Point_OnRayP '(25 10) '(10 10) '(20 10) 0.0001)
;  ==> T
;
;  (ALE_Point_OnRayP '(15 10) '(10 10) '(20 10) 0.0001)
;  ==> nil
;
;  (ALE_Point_OnRayP '(5 10) '(10 10) '(20 10) 0.0001)
;  ==> nil
;
(defun ALE_Point_OnRayP (TstPtn Pnt001 Pnt002 FuzFac)
  (cond
    ( (not
        (and
          (listp TstPtn) (listp Pnt001) (listp Pnt002)
          (numberp FuzFac)
        )
      )
      (alert "Not valid data!")
    )
    ( (and
        (equal (angle Pnt001 Pnt002) (angle Pnt002 TstPtn) FuzFac)
        (equal (angle Pnt002 Pnt001) (angle TstPtn Pnt001) FuzFac)
      )
    )
  )
)

Qualche miglioramento:
; Marc'Antonio Alessi, Italy - 
http://xoomer.virgilio.it/alessi
;
; Function: ALE_Point_AlongXLineP
;
; External functions: ALE_List_CheckTypes
;
; Version 1.00 - 25/11/2006
;
; Arguments:
;   TstPtn: test point
;   Pnt001: first point
;   Pnt002: second point
;   FuzFac: a real number defining the maximum amount by which 
;           points can differ and still be considered equal
;   BitFlg:
;           1 > point is between Pnt001 and Pnt002
;           2 > point is on Ray starting from Pnt001 but not between
;           4 > point is on Ray starting from Pnt002 but not between
;     e.g.:
;           6 > point is on Xline but not between Pnt001 and Pnt002
;           7 > point is on Xline
;
; Return Values: T or nil
;
(defun ALE_Point_AlongXLineP (TstPtn Pnt001 Pnt002 FuzFac BitFlg /
                              Dst1_2 Dst1_T Dst2_T OutBit)
  (cond
    ( (not
        (ALE_List_TypesP
          (list TstPtn Pnt001 Pnt002 FuzFac BitFlg)
          (list 'LIST  'LIST  'LIST  'REAL  'INT  )
        )
      )
      (alert "Not valid data!")
    )
    ( (setq
        Dst1_2 (distance Pnt001 Pnt002)  Dst1_T (distance Pnt001 TstPtn)
        Dst2_T (distance Pnt002 TstPtn)  OutBit 0
      )
      (cond
        ( (equal (+ Dst1_T Dst2_T) Dst1_2 FuzFac) (setq OutBit 1) )
        ( (equal (- Dst1_T Dst2_T) Dst1_2 FuzFac) (setq OutBit 2) )
        ( (equal (- Dst2_T Dst1_T) Dst1_2 FuzFac) (setq OutBit 4) )
      )
      (eq OutBit (logand OutBit BitFlg))
    )
  )
)
;
; Marc'Antonio Alessi, Italy - 
http://xoomer.virgilio.it/alessi
;
; Function: ALE_List_TypesP
;
; Version 1.00 - 24/11/2006
;
; Description:
;   Returns T if the type of every element in <list> is the type
;   designated of every element in <typelist> in order, which is
;   a list of the possible symbols returned by the (type) function
;   (e.g., 'INT 'STR 'REAL etc.).
;   Returns NIL otherwise.
;
; Examples:
; (ALE_List_TypesP '(1 "A" 1.0) (list 'INT 'STR 'REAL))
; ==> T
;
; (ALE_List_TypesP '(1  1.0) (list 'INT 'STR 'REAL))
; ==> nil
;
; (ALE_List_TypesP '(1 '(1) 1.0) (list 'INT 'STR 'REAL))
; ==> nil
;
; (ALE_List_TypesP '(1 '(1) 1.0) (list 'INT 'REAL 'LIST))
; ==> nil
;
; (ALE_List_TypesP '(1 1.0 '(1)) (list 'INT 'REAL 'LIST))
; ==> T
;
(defun ALE_List_TypesP (In_Lst TypLst / OutFlg)
  (and
    (not
      (vl-catch-all-error-p
        (setq OutFlg
          (vl-catch-all-apply
           'vl-every
            (list
             '(lambda (LmbDat LmbDt1)
                (eq (type LmbDat) LmbDt1)
              )
              In_Lst TypLst
            )
          )
        )
      )
    )
    OutFlg
  )
)
;
; Marc'Antonio Alessi, Italy - 
http://xoomer.virgilio.it/alessi
;
; Function: ALE_Point_OnLineP
;
; External functions: ALE_List_CheckTypes
;
; Version 1.00 - 16/04/2000
; Version 1.01 - 24/11/2006
; Version 1.02 - 25/11/2006
;
; Arguments:
;   TstPtn:  test point
;   Pnt001:  first point
;   Pnt002:  second point
;   FuzFac:  a real number defining the maximum amount by which 
;            points can differ and still be considered equal
;
; Return Values: T or nil
;
; Examples:
;  (ALE_Point_OnLineP '(10 10) '(10 10) '(20 10) 0.0001)
;  ==> T
;
;  (ALE_Point_OnLineP '(10 10) '(20 20) '(30 30) 0.0001)
;  ==> nil
;
(defun ALE_Point_OnLineP (TstPtn Pnt001 Pnt002 FuzFac)
  (cond
    ( (not
        (ALE_List_TypesP
          (list TstPtn Pnt001 Pnt002 FuzFac)
          (list 'LIST  'LIST  'LIST  'REAL)
        )
      )
      (alert "Not valid data!")
    )
    ( (equal
        (+ (distance Pnt001 TstPtn) (distance Pnt002 TstPtn))
        (distance Pnt001 Pnt002)
        FuzFac
      )
    )
  )
)
;
; Marc'Antonio Alessi, Italy - 
http://xoomer.virgilio.it/alessi
;
; Function: ALE_Point_OnXLineP
;
; External functions: ALE_List_CheckTypes
;
; Version 1.00 - 24/11/2006
; Version 1.02 - 25/11/2006
;
; Arguments:
;   TstPtn:  test point
;   Pnt001:  first point
;   Pnt002:  second point
;   FuzFac:  a real number defining the maximum amount by which 
;            points can differ and still be considered equal
;
; Return Values: T or nil
;
; Examples:
;  (ALE_Point_OnXLineP '(50 10) '(10 10) '(20 10) 0.0001)
;  ==> T
;
;  (ALE_Point_OnXLineP '(15 10) '(10 10) '(20 10) 0.0001)
;  ==> nil
;
;  (ALE_Point_OnXLineP '(05 10) '(10 10) '(20 10) 0.0001)
;  ==> T
;
;  (ALE_Point_OnXLineP '(50 10) '(10 10) '(20 11) 0.0001)
;  ==> nil
;
(defun ALE_Point_OnXLineP (TstPtn Pnt001 Pnt002 FuzFac / Dst1_2 Dst1_T Dst2_T)
  (cond
    ( (not
        (ALE_List_TypesP
          (list TstPtn Pnt001 Pnt002 FuzFac)
          (list 'LIST  'LIST  'LIST  'REAL)
        )
      )
      (alert "Not valid data!")
    )
    ( (setq
        Dst1_2 (distance Pnt001 Pnt002)
        Dst1_T (distance Pnt001 TstPtn)
        Dst2_T (distance Pnt002 TstPtn)
      )
      (or
        (equal (+ Dst1_T Dst2_T) Dst1_2 FuzFac)
        (equal (- Dst1_T Dst2_T) Dst1_2 FuzFac)
        (equal (- Dst2_T Dst1_T) Dst1_2 FuzFac)
      )
    )
  )
)
; Marc'Antonio Alessi, Italy - 
http://xoomer.virgilio.it/alessi
;
; Function: ALE_Point_OnRayP
;
; External functions: ALE_List_CheckTypes
;
; Version 1.00 - 24/11/2006
; Version 1.02 - 25/11/2006
;
; Arguments:
;   TstPtn:  test point
;   Pnt001:  first point > start point of ray
;   Pnt002:  second point
;   FuzFac:  a real number defining the maximum amount by which 
;            points can differ and still be considered equal
;
; Return Values: T or nil
;
; Examples:
;  (ALE_Point_OnRayP '(25 10) '(10 10) '(20 10) 0.0001)
;  ==> T
;
;  (ALE_Point_OnRayP '(15 10) '(10 10) '(20 10) 0.0001)
;  ==> nil
;
;  (ALE_Point_OnRayP '(05 10) '(10 10) '(20 10) 0.0001)
;  ==> nil
;
;  (ALE_Point_OnRayP '(50 10) '(10 10) '(20 11) 0.0001)
;  ==> nil
;
(defun ALE_Point_OnRayP (TstPtn Pnt001 Pnt002 FuzFac / Dst1_2 Dst1_T Dst2_T))
  (cond
    ( (not
        (ALE_List_TypesP
          (list TstPtn Pnt001 Pnt002 FuzFac)
          (list 'LIST  'LIST  'LIST  'REAL)
        )
      )
      (alert "Not valid data!")
    )
    ( (setq
        Dst1_2 (distance Pnt001 Pnt002)
        Dst1_T (distance Pnt001 TstPtn)
        Dst2_T (distance Pnt002 TstPtn)
      )
      (or
        (equal (+ Dst1_T Dst2_T) Dst1_2 FuzFac)
        (equal (- Dst1_T Dst2_T) Dst1_2 FuzFac)
      )
    )
  )
)


Per controllare semplicemente se 3 punti sono allineati.
-------------------------------------------------
(defun PPP ( / toll)
(setq P1 (getpoint "\nSelezionare il punto1 o fornire le sue coordinate"))
(setq P2 (getpoint "\nSelezionare il punto2 o fornire le sue coordinate"))
(setq P3 (getpoint "\nSelezionare il punto3 o fornire le sue coordinate\n"))
 (setq toll 1.0e-012)
   (equal
      '(0.0 0.0 0.0)
      ( Prod-Vett (mapcar '- P2 P1) (mapcar '- P3 P1))
      toll
   ) ;fine equal
) ;fine PPP
(defun Prod-Vett (v1 v2)
   (list
      (- (* (cadr v1) (caddr v2)) (* (caddr v1) (cadr v2)))
      (- (* (caddr v1) (car v2)) (* (car v1) (caddr v2)))
      (- (* (car v1) (cadr v2)) (* (cadr v1) (car v2)))
   ) ;fine list
) ;fine Prod-Vett
-------------------------------------------------------------------
Esistono altre routines simili (condiz di perpend di 2 segm, di appart. di 3
punti a un piano, area di un triangolo, ecc).
Joseph
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 punto "C" si trova all'interno del segmento AB.
.............................................
Scusate se riprendo l'argomento.
Lo studio, da poco ripreso, di questo linguaggio e la mia innata curiosità
mi hanno spinto a cercare se poteva esistere una soluzione alternativa al
problema; da (antichi) ricordi universitari si sa che 2 vettori (P1-P2) e
(P1-P3) sono allineati quando il loro Prodotto Vettoriale é nullo. Per cui,
spulciando in rete su un sito tedesco (naturalmente con annotazioni in
inglese) , mi sono imbattuto nella traduzione in linguaggio Lisp di questo
proprietà che, adattata al caso nostro, ha dato origine a questa soluzione
che vi allego (migliorando l'ultima versione che avevo allegato
precedentemente).
Saluti
(defun PPP ()
  (setq P1 (getpoint "\nSelezionare il punto1 o immettere X,Y,Z"))
  (setq P2 (getpoint "\nSelezionare il punto2 o immettere X,Y,Z"))
  (setq P3 (getpoint "\nSelezionare il punto3 o immettere X,Y,Z"))
  (setq toll 0.00001)
  (if
    (equal '(0.0 0.0 0.0) (Prod-Vett (mapcar '- P2 P1) (mapcar '- P3 P1)) toll)
     (progn
       (if
	 (> (distance P2 P1) (distance P3 P1))
	  (prompt "Punto P3 allineato ed interno al segmento P1-P2")
	  (prompt "Punto P3 allineato ed esterno al segmento P1-P2")
       ) ;fine if
     ) ;fine progn
     (prompt "Punto P3 non allineato")
  ) ;fine if
  (princ)
) ;fine PPP
(defun Prod-Vett (v1 v2)
  (list
    (- (* (cadr v1) (caddr v2)) (* (caddr v1) (cadr v2)))
    (- (* (caddr v1) (car v2)) (* (car v1) (caddr v2)))
    (- (* (car v1) (cadr v2)) (* (cadr v1) (car v2)))
  ) ;fine list
) ;fine Prod-Vett
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 Saluti
<clip>
Joseph,
la soluzione è interessante ma non credi che paragonare le distanze con
(distance .. ..) sia sufficiente?
Marco


In che senso?


 In che senso?
In tutti i sensi!
Cioè senza andarsi a complicare la vita con:
(equal '(0.0 0.0 0.0) (Prod-Vett (mapcar '- P2 P1) (mapcar '- P3 P1)) toll)
e



Se mi fossi limitato a paragonare le distanze, potevo solamente concludere
che P3 era piů vicino in valore assoluto (o piů lontano) del punto P2,
rispetto a P1, ma non potevo dedurre che i 3 punti erano sicuramente
allineati e neppure che P2 era interno (o esterno) al segmento P1-P2.
Ma volevo sentire l'opinione anche di chi ha fatto la richiesta, nel caso
avesse trovato delle situazioni in cui il programma fallisce.
A risentirci


 allineati e neppure che P2 era interno (o esterno) al segmento P1-P2.
<clip>
Hai provato:
; Funzione: ALE_Point_AlongXLineP
;
; Argomenti:
;   TstPtn: punto da testare
;   Pnt001: primo punto
;   Pnt002: secondo punto
;
;   BitFlg:
;   1 > il punto è tra Pnt001 e Pnt002
;   2 > il punto è sul Raggio che parte da Pnt001 ma non tra Pnt001 e Pnt002
;   4 > il punto è sul Raggio che parte da Pnt002 ma non tra Pnt001 e Pnt002
;   es.:
;   6 = (4 + 2)     > il punto è sulla XLinea ma non tra Pnt001 e Pnt002
;   7 = (1 + 2 + 4) > il punto è sulla XLinea
il tutto funziona solo con:
      (setq
        Dst1_2 (distance Pnt001 Pnt002)  Dst1_T (distance Pnt001 TstPtn)
        Dst2_T (distance Pnt002 TstPtn)  OutBit 0
      )
      (cond
        ( (equal (+ Dst1_T Dst2_T) Dst1_2 FuzFac) (setq OutBit 1) )
        ( (equal (- Dst1_T Dst2_T) Dst1_2 FuzFac) (setq OutBit 2) )
        ( (equal (- Dst2_T Dst1_T) Dst1_2 FuzFac) (setq OutBit 4) )
      )
      (eq OutBit (logand OutBit BitFlg))
Può darsi che mi sbagli ma mi pare che funzioni.
Ciao.
Marco


Funziona certo, come le altre; mi sembra limitativo assegnare il valore alla
variabile BitFlg nel momento in cui si richiama la funzione, perchè se le
assegni "1" ed esce "nil" sai solamente che il punto di controllo non sta
tra p1 2 p2, ma non sai dove è veramente, se sulla Xlinea o no, a meno di
fare un secondo controllo con un altro valore di BitFlg (d'accordo, la
richiesta era in realtà limitata, tentavo solo, con la mia soluzione, di
dare una risposta più globale).
Sto imparando veramente molte cose, confrontando tra loro le tue soluzioni.


 A risentirci
Forse non hai ben capito l'uso della funzione,
se vuoi sapere se il punto di controllo sta sulla XLinea devi usare:
 (ALE_Point_AlongXLineP '(10 10) '(10 10) '(20 10) 0.0001 7)
In pratica a seconda del valore di BitFlg, che può essere un singolo bit
o la somma di più bit puoi sapere se il punto si trova in tutte le
seguenti condizioni:
;   BitFlg:
;   1 > il punto è tra Pnt001 e Pnt002
;   2 > il punto è sul Raggio che parte da Pnt001 ma non tra Pnt001 e Pnt002
;   4 > il punto è sul Raggio che parte da Pnt002 ma non tra Pnt001 e Pnt002
;   es.:
;   3 = (2 + 1)     > il punto è sul Raggio che parte da Pnt002
;   5 = (4 + 1)     > il punto è sul Raggio che parte da Pnt001
;   6 = (4 + 2)     > il punto è sulla XLinea ma non tra Pnt001 e Pnt002
;   7 = (1 + 2 + 4) > il punto è sulla XLinea
Ciao.
Marco

Aggiungo:
- la funzione "Prod-Vett" accetta punti solo in formato 3D (con Z)
  e va in errore se vengono passati punti in 2D (senza Z)
  (ad esempio se usi dei punti ricavati da una LwPolyLine)
Comando: (Prod-Vett '(10 20 30) '(15 25 35))
(-50 100 -50)
Comando: (Prod-Vett '(10 20 30) '(15 25))
; errore: tipo di argomento errato: numberp: nil
- tutte le funzioni "ALE_Point_xxx" accettano punti 2D o 3D
  e si comportano di conseguenza come specificato sotto
Help di AutoCAD:
Distance:
Returns the 3D distance between two points
(distance pt1 pt2)
Arguments:
pt1 = A 2D or 3D point list.
pt2 = A 2D or 3D point list.
Return Values: The distance.
If one or both of the supplied points is a 2D point, then distance ignores the Z 
coordinates of any 3D points supplied and returns the 2D distance between the 
points as projected into the current construction plane.
--
Ciao.
Marco 


Il ProdVett funziona anche con vettori 2D: la funzione avrà una struttura
più semplice (un controllo iniziale sarà sufficiente per usare l'opzione 2D
o 3D)
Nel caso di immissione mista sarà sufficiente aggiungere Z=0 ai punti 2D; ma
anche il comando "distance" presenta problemi in questo caso: se immetti
punti 2D e 3D, la distanza fornita non è quella reale, ma quella fra i 2
punti proiettati sul piano di costruzione, ignorando quindi la coord. Z.
Ciao
Joseph
 
Nel caso di immissione mista



Che ne dici di questa variante?
(defun all ()
  (arxload "geomcal")
  (setq p1 '(0 -2 0)
	p2 '(2 0 4)
	p3 '(1 -1 2) ; p3 =(1 -1 2) interno
  ) ; p3= (-1 -3 -2)) esterno
  (setq vers12 (cal "vec1(p1,p2)")
	vers13 (cal "vec1(p1,p3)")
	L12 (cal "abs (p1-p2)")
	L13 (cal "abs (p1-p3)")
  )
  (if (and (equal vers12 vers13 0.000001) (> L12 L13))
    (prompt "punto P3 interno")
    (prompt "punto P3 esterno")
  )
  (princ)
)
Manca solo la verifica se P3 si trova sulla Xlinea o no, nel caso sia
esterno.
Ciao
Joseph


> Che ne dici di questa variante?
<clip>
Joseph,
non ho testato completamente la funzione, potrebbe essere una
soluzione diversa, ma se dovessimo usare ripetute volte queste
funzioni per testare migliaia di punti il risultato potrebbe
essere questo:
(test eseguito su versioni semplificate, vedi sotto, per un
confronto omogeneo)
(PPP_P                 '(15 10 0) '(10 10 0) '(20 10 0) 0.0001)
(ALE_Point_AlongXLineP '(15 10 0) '(10 10 0) '(20 10 0) 0.0001 7)
(all_P                 '(15 10 0) '(10 10 0) '(20 10 0))
  esecuzione in millisecondi / velocita relativa per 16384 iterationi:
ALE_POINT_ALONGXLINEP ..1262 / 25.86 <più veloce>
PPP_P ..................1823 / 17.9
ALL_P .................32637 /  1.0  <più lenta >
in sostanza ALE_POINT_ALONGXLINEP è circa 26 volte più veloce di ALL_P,
senza considerare che restituisce una risposta più completa.
Ciao.
Marco
%%
(defun all_P (p1 p2 p3 / vers12 vers13 L12 L13)
  (setq vers12 (cal "vec1(p1,p2)")
        vers13 (cal "vec1(p1,p3)")
        L12    (cal "abs (p1-p2)")
        L13    (cal "abs (p1-p3)")
  )
  (and (equal vers12 vers13 0.000001) (> L12 L13))
)
(defun ALE_Point_AlongXLineP (TstPtn Pnt001 Pnt002 FuzFac BitFlg /
                                     Dst1_2 Dst1_T Dst2_T OutBit)
  (setq
    Dst1_2 (distance Pnt001 Pnt002)  Dst1_T (distance Pnt001 TstPtn)
    Dst2_T (distance Pnt002 TstPtn)  OutBit 0
  )
  (cond
    ( (equal (+ Dst1_T Dst2_T) Dst1_2 FuzFac) (setq OutBit 1) )
    ( (equal (- Dst1_T Dst2_T) Dst1_2 FuzFac) (setq OutBit 2) )
    ( (equal (- Dst2_T Dst1_T) Dst1_2 FuzFac) (setq OutBit 4) )
  )
  (eq OutBit (logand OutBit BitFlg))
)
(defun PPP_P (p1 p2 p3 toll / )
  (if
    (equal
      '(0.0 0.0 0.0)
       (Prod-Vett (mapcar '- P2 P1) (mapcar '- P3 P1))
       toll
    )
    (if (> (distance P2 P1) (distance P3 P1))
      1
      2
    )
  )
)
%%
(defun Prod-Vett (v1 v2)
  (list
    (- (* (cadr v1) (caddr v2)) (* (caddr v1) (cadr v2)))
    (- (* (caddr v1) (car v2)) (* (car v1) (caddr v2)))
    (- (* (car v1) (cadr v2)) (* (cadr v1) (car v2)))
  )
)

 Dovevo immaginare che richiamare 4 volte la funzione CAL avrebbe ritardato
la soluzione: difatti non soddisfa neppure me.
Ti chiedo (e poi penso che la discussione si possa concludere):per il ciclo
di iterazione, in questo caso di confronto fra soluzioni diverse, quale
funzione è preferibile usare (repeat, while, ecc) o altri metodi più
semplici che io non conosco?
Grazie di tutto
Buon weekend


 semplici che io non conosco?
Ho diverse funzioni per il "Benchmark", quella più interessante non è mia
ed è protetta dal Copyright perciò non la posso pubblicare qui.
Ti ho inviato la funzione al tuo indirizzo.
Saluti.
Marco
-- 
----------------------------------------------------------
Marc'Antonio Alessi - 
http://xoomer.virgilio.it/alessi
Per AutoCAD:
- Travi 2D: disegno automatico travi e pilastri in C.A.,
  relativi ferri e staffe, report peso ferri e C.A.
  su Excel
- Calcolo automatico aree su planimetrie: report su Excel
  per locale altezza, piano con descrizioni locali e piani
- Elaborazione dati from/to Excel
- Librerie manufatti in assonometria
- Autolayers: gestione automatica dei layers
- Elaborazioni e stampe multiple e automatiche
- Parametrico 2D, Viterie 2D/3D, Esplosi 2D/3D
- AutoGroups: gestione automatica gruppi di layers
- SetUp del disegno con gestione automatica DimStyles
- Conversione automatica files Inventor a DWG e viceversa
  anche senza avere Inventor installato
- ...
----------------------------------------------------------

 Marco
 
Che dire? Grazie infinite.
Buona Domenica


> Che dire? Grazie infinite.
Prego e buona Domenica.
Marco