;********************************************************************
;* Comando: Gvista ()
;* Comentarios: este comando se usa para generar los cortes y las
;* distintas vistas (x,y,z,-x,-y,-z,3d) de la subestacion a partir
;* de plano 3d de esta. El comando pregunta la vista que se desea
;* generar y los objetos a los cuales se les quiere crear la vista
;* .Si la vista no existe para un bloque, se copia el bloque mismo
;* en caso contrario se reemplaza el bloque por la vista dada. La
;* vista generada se convierte en bloque.
;********************************************************************ÿ

; Change log
;
; 25/10/94 C. Perigault   Modifique la insercion del bloque para que
;                         fuera en el mismo lugar que el alambre
;
; 25/10/94 C. Perigault   Modifique la escala del bloque para que 
;                         fuera la misma que el bloque alambre
;
;  8/11/94 C. Perigault   Agrege el sinonimo genera-vista para mantener
;                         la compatibilidad con la memoria
;
; 8/11/94  C. Perigault   Elime la vista 3d ya que no es necesaria
;
;
; 8/11/94  C. Perigualt   Cambie la forma de insertar la vista, ahora
;                         el ucs se situa en la entidad y se inserta 
;                         la vista para que esta tenga misma posicion
;                         y rotacion que la original.
;
(defun c:genera-vista () (c:Gvista)) ; sinonimo

(defun c:Gvista ( / osmode cmdecho gridmode ListaVistas ListaRotacion
			 conjunto NumeroDeEntidades NuevoConjunto i entidad
			 TipoEntidad NombreBloqueNuevo NombreBloque
			 sufijo prefijo  temp BloqueNuevo)

  (setq ucs 1)
  (setq wcs 0)
;******************************************************************
;* Funcion    : Prefijo (vista entidad)
;* Parametros :
;*              - vista   : (x y z)
;*              - entidad : nombre de una entidad
;* Retorna :
:* Un string que contiene el nombre de la vista , de no corresponder
;* a una de las vista normalizadas retorna "null".
;* Comentarios: Esta funcion es la base para encontrar el
;* bloque que se debe utilizar
;******************************************************************
(defun PrefijoVista (vista entidad / ListaVistas)
  ; En esta lista se define la correspondencia entre la vista y
  ; el prefijo que corresponde a la vista
  (setq ListaVistas '((( 1  0  0)  "x" )
		      (( 0  1  0)  "y" )
		      (( 0  0  1)  "z" )
		      ((-1  0  0) "-x" )
		      (( 0 -1  0) "-y" )
		      (( 0  0 -1) "-z" )))
  
      ; transformamos la vista al wcs que es el que usamos como
      ; referencia
      ;;; (setq vista (trans vista ucs wcs))
      ; el sistema de coordenadas es ahora el de la entidad
      (command "UCS" "E" entidad)
      ; convertimos la vista del wcs a ucs que ahora equivale al
      ; sistema de coordenadas de la entidad
      (setq vista (VectorUnitario (RestaVector
				    (trans   vista  wcs ucs)
				    (trans '(0 0 0) wcs ucs))))
      ; Redondeamos la vista para que no tengamos problemas por
      ; errores de precision
      (setq vista (list
		    (redondea (car   vista))
		    (redondea (cadr  vista))
		    (redondea (caddr vista))))
      ; volvemos al sistema de coordenadas desde el cual nos
      ; llamaron
      (command "UCS" "P")
      ; si existe el prefijo retornamos el prefijo en caso
      ; contrario retormamos "null"
      (if (cadr(assoc vista ListaVistas))
	(cadr (assoc vista ListaVistas))
	"null"))
;******************************************************************
;* Funcion    : RestaVector(v1 v2)
;* Parametros :
;*             - v1 : (x1 y1 z1)
;*             - v2 : (x2 y2 z2)
;* Retorna : La resta  v1-v2 en la forma ( x y z)
;******************************************************************

(defun RestaVector (v1 v2)
  (list (- (car   v1)(car   v2))
	(- (cadr  v1)(cadr  v2))
	(- (caddr v1)(caddr v2))))

;******************************************************************
;* Funcion : Redondea (x)
;*
;*
;******************************************************************
(defun Redondea (x)
   (if (minusp x) (fix (- x 0.5)) (fix (+ x 0.5))))
;******************************************************************
;* Funcio:VectorUnitario (v)
;* Parametros:
;*              - v :(x y z)
;*
;* Retorna: El vector unitario de v en la forma ( x y z)
;******************************************************************

(defun VectorUnitario (v / temp x y z)
  (setq x (car v) y (cadr v) z (caddr v))
  (setq temp (+ (* x x) (* y y) (* z z)))
  (list
    (/ x temp)
    (/ y temp)
    (/ z temp)))
;********************************************************************
;* Funcion : Rotacion (conjunto punto fi teta)
;* Parametros :
;*              - conjunto : entidades que se desean rotar
;*              - punto    : punto de rotacion
;*              - fi       : rotacion en el plano xy
;*              - teta     : rotacion con respecto al eje z
;*
;********************************************************************
(defun Rotacion (conjunto  punto fi teta)
  (setq punto (trans punto ucs wcs))
  (command "ROTATE" conjunto "" (trans punto wcs ucs)  fi)
  (command "UCS" "Y" "-90")
  (command "ROTATE" conjunto "" (trans punto wcs ucs)  teta)
  (command "UCS" "P"))




  ; cambiamos las varibles del sistema para que no interfieran con
  ; los comandos y para hacer mas rapida la ejecucion.
  (setq osmode   (getvar "OSMODE"  ))
  (setq cmdecho  (getvar "CMDECHO" ))
  (setq gridmode (getvar "GRIDMODE"))
  (setvar "GRIDMODE" 0)
  (setvar "CMDECHO"  0)
  (setvar "OSMODE"   0)
  ;En esta lista guardamos la relacion que hay entre el nombre
  ;de la vista y su coordenada
  (setq ListaVistas '( ( "x"  ( 1  0  0))
		       ( "y"  ( 0  1  0))
		       ( "z"  ( 0  0  1))
		       ( "-x" (-1  0  0))
		       ( "-y" ( 0 -1  0))
		       ( "-z" ( 0  0 -1))))
		       
  ;Esta lista guarda la relacion entre la vista y las rotacines
  ;necesarias para ponerlos en el plano xy
  (setq ListaRotacion '( ( ( 1  0  0)( -90  90))
			 ( ( 0  1  0)( 180  90))
			 ( ( 0  0  1)(   0   0))
			 ( (-1  0  0)(  90  90))
			 ( ( 0 -1  0)(   0  90))
			 ( ( 0  0 -1)(   0 180))
			 ( ( 1  1  1)(   0   0))))
  ;Ingreso de datos por parte del usuario
  (initget 1 "x y z -x -y -z")
  (setq vista   (strcase (getstring "\nIngrese vista x/y/z/-x/-y/-z:") t))
  (setq vista   (cadr (assoc vista ListaVistas)))
  (setq conjunto (ssget))
  (setq NumeroDeEntidades (sslength conjunto))
  (setq i 0)
  (setq NuevoConjunto nil)

  ;Para todo el conjunto seleccionado hacemos una nueva copia
  ;y modificamos los bloques que tengan vistas
  (repeat NumeroDeEntidades
    (setq NombreEntidad (ssname conjunto i))
    (setq i (+ i 1))
    (setq entidad (entget NombreEntidad))
    (setq TipoEntidad (cdr (assoc 0 entidad)))
    (command "copy" NombreEntidad "" '(0 0 0)  '(0 0 0))
    (if NuevoConjunto
      (ssadd (entlast) NuevoConjunto)
      (setq NuevoConjunto (ssadd (entlast))))
    ; Si es un bloque modificamos para crear la nueva vista
    ; si existe esta en caso contrario copiamos el bloque.
    (if (equal TipoEntidad "INSERT")
      (progn
        (command "UCS" "E" (cdr (assoc -1 entidad)))
	(setq NombreBloque (cdr (assoc 2 entidad)))
	(setq sufijo  (substr NombreBloque 4 255))
	(setq prefijo (PrefijoVista vista NombreEntidad))
	(setq NombreBloqueNuevo  (strcat prefijo sufijo))
        ;
        ; Punto de insercion del nuevo bloque
        ;
        (setq insercionBloqueNuevo (cdr (assoc 10 entidad)))
	;
        ; Factores de escala
        ;
         
        (setq escalaXBloqueNuevo (cdr (assoc 41 entidad)))
        (setq escalaYBloqueNuevo (cdr (assoc 42 entidad)))
        (setq escalaZBloqueNuevo (cdr (assoc 43 entidad)))



        ; Vemos si el bloque a insertar tiene un vista
	; si no la tiene insertamos el mismo bloque
	; en caso contrario insertamos la vista
	(if (tblsearch "BLOCK" NombreBloqueNuevo)
	  (progn
	    (setq BloqueNuevo (entget (entlast)))
	    ; si existe la vista borramos el bloque
            ;(setq NombreEntidadConVista (entlast))

	    (setq NuevoConjunto (ssdel (entlast) NuevoConjunto))
	    (entdel (entlast))

	   ;(command "Insert" NombreBloqueNuevo '(0 0 0) "" "" "" )
	    (command "Insert" NombreBloqueNuevo  '(0 0 0) "XYZ" 
                   escalaXBloqueNuevo escalaYBloqueNuevo escalaZBloqueNuevo "" )
            (command "UCS" "W")
           (if NuevoConjunto
	      (ssadd (entlast) NuevoConjunto)
	      (setq NuevoConjunto (ssadd (entlast))))
	    ; modificamos la lista de definicion del bloque original
	    ; para utilizarla en la vista que se inserto
	    (setq BloqueNuevo (subst (assoc -1 (entget (entlast))) (assoc -1 BloqueNuevo) BloqueNuevo))
	    (setq BloqueNuevo (subst (cons 2 NombreBloqueNuevo) (cons 2 NombreBloque) BloqueNuevo))
	    (setq BloqueNuevo (subst (cons 66 0) (assoc 66 entidad) BloqueNuevo))
            
	    (entmod BloqueNuevo))))))
    ;Procedemos a rotar las entidades
    (grclear)
    (command "SELECT" NuevoConjunto "")
    (setq temp (cadr (assoc vista ListaRotacion)))
    (setq fi (car temp) teta (cadr temp))
    (setq punto (getpoint "\nIngrese punto de rotacion: "))
    (if punto (rotacion NuevoConjunto punto fi teta))
    ;Procedemos a crear el bloque
    (setq viewdir (getvar "VIEWDIR"))
    ; seleccionamos la vista superior por ser la vista desde donde
    ; se insertan los bloque que continenen las distintas vistas
    (command "VPOINT" '(0 0 1))
    (grclear)
    (command "SELECT" NuevoConjunto "")
    (setq nombre (getstring "\nIngrese nombre del bloque: "))
    (setq punto (getpoint "\nPunto de insercion: "))
    ; Buscamos el nombre del bloque (de la vista) a ver si este ya existe
    ; de existir se le pregunta al usuario si desea redefinirlo
    ; en caso contrario se crea el nuevo bloque
    (if (tblsearch "BLOCK" nombre)
      (progn
	(princ (strcat "\nEl nombre " nombre " ya existe"))
	(initget 1 "S N")
	(if (equal (strcase (getstring "\nRedefinirlos (s/n): ") t) "s")
	  (command "BLOCK"  nombre "Y" punto  NuevoConjunto "")
	  (command "ERASE" NuevoConjunto "")))
      (command "BLOCK" nombre punto NuevoConjunto ""))
    ; retormamos al estado de acad cuando lo llamo el usuario
    (command "UCS" "W" )
    (command "VPOINT" viewdir)
    (setvar "GRIDMODE" gridmode)
    (setvar "OSMODE"   osmode  )
    (setvar "CMDECHO"  cmdecho ))

