;;; ENDTICK.LSP
;;;
;;; Copyright 2006 Thomas Gail Haws
;;; This program is free software under the terms of the
;;; GNU (GNU--acronym for Gnu's Not Unix--sounds like canoe)
;;; General Public License as published by the Free Software Foundation,
;;; version 2 of the License.
;;;
;;; You can redistribute this software for any fee or no fee and/or
;;; modify it in any way, but it and ANY MODIFICATIONS OR DERIVATIONS
;;; continue to be governed by the license, which protects the perpetual
;;; availability of the software for free distribution and modification.
;;;
;;; You CAN'T put this code into any proprietary package.  Read the license.
;;;
;;; If you improve this software, please make a revision submittal to the
;;; copyright owner at www.hawsedc.com.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;; GNU General Public License on the World Wide Web for more details.
;;;
;;; DESCRIPTION
;;;
;;; ENDTICK inserts and aligns the ENDTICK block at the endpoint of every arc or line
;;; in a selection set.  It removes duplicate ticks.
;;;
;;; ENDTICK is useful for surveying and civil engineering plans to demarcate points of
;;; curvature, tangency, et cetera.
;;;
;;; You can make your own ENDTICK block if you prefer some custom shape or size tick.
;;; The default ENDTICK block is a one unit long vertical line with its insertion point
;;; at its midpoint.  ENDTICK scales the ticks to the dimension text height
;;; (dimscale * dimtext), so the default ENDTICK block will look as big as the current
;;; dimension text height.
;;;
;;; Revisions
;;; 20060914  TGH   Version 1.0PR released.  3 hrs.  Works only with world UCS and View 

(defun c:ENDTICK () (ENDTICK))

(defun
   ENDTICK
	   ;;No global variables.  All the variables should be listed here as local.
	   (/		CENPOINT    DS		DT	    ENDANG
	    ENDPOINT	ENTLIST	    ENTNAME	ENTTYPE	    I
	    MINTICKSEPARATION	    RADIUS	SS1	    STARTANG
	    STARTPOINT	TICKLIST    TS
	   )
  ;;Set initial variables
  (setq
    ds (getvar "dimscale")
    dt (getvar "dimtxt")
    ts (* ds dt)
    ;;If endpoints are closer together than the distance given below
    ;; and also aligned angularly closer than the angular difference below,
    ;; ENDTICK only plots the first one of them it finds.
    mintickseparation
     (* ts 0.01)
    ;;In radians.  Setting to some big number like 10 (larger than 2 pi) will remove coincident ticks even with different rotations.
    mintickangulardif
     0.01
  )
  ;;Get selection set from user.  Limit to lines and arcs.
  (setq
    ss1	(ssget '((0 . "LINE,ARC")))
    i	-1
  )
  ;;Get endpoints and orientations from selection set
  (while (setq entname (ssname ss1 (setq i (1+ i))))
    (setq
      entlist
       (entget entname)
      enttype
       (cdr (assoc 0 entlist))
    )
    (cond
      ((= enttype "LINE")
       (setq
	 startpoint
	  (cdr (assoc 10 entlist))
	 endpoint
	  (cdr (assoc 11 entlist))
	 ticklist
	  (ENDTICK-addtolist
	    (list startpoint (angle startpoint endpoint))
	    ticklist
	    mintickseparation
	    mintickangulardif
	  )
	 ticklist
	  (ENDTICK-addtolist
	    (list
	      endpoint
	      (angle endpoint startpoint)
	    )
	    ticklist
	    mintickseparation
	    mintickangulardif
	  )
       )
      )

      ((= enttype "ARC")
       (setq
	 cenpoint
	  (cdr (assoc 10 entlist))
	 radius
	  (cdr (assoc 40 entlist))
	 startang
	  (cdr (assoc 50 entlist))
	 endang
	  (cdr (assoc 51 entlist))
	 startpoint
	  (polar cenpoint startang radius)
	 endpoint
	  (polar cenpoint endang radius)
	 ticklist
	  (ENDTICK-addtolist
	    (list startpoint (+ startang (/ pi 2)))
	    ticklist
	    mintickseparation
	    mintickangulardif
	  )
	 ticklist
	  (ENDTICK-addtolist
	    (list endpoint (+ endang (/ pi 2)))
	    ticklist
	    mintickseparation
	    mintickangulardif
	  )
       )
      )
    )
  )
  (setq auold (getvar "aunits"))
  (setvar "aunits" 3)
  (foreach
     tick ticklist
    (command "._insert" "endtick" (car tick) ts "" (cadr tick))
  )
  (setvar "aunits" auold)
)

(defun
   ENDTICK-addtolist
		     (tick	      ticklist	      mintickseparation
		      mintickangulardif		      /
		      dupfound	      templist	      tickcheck
		     )
  ;;Look for duplicates in list
  (setq templist ticklist)
  (while (setq tickcheck (car templist))
    (if	(and
	  (< (distance (car tick) (car tickcheck)) mintickseparation)
	  (< (abs (- (cadr tick) (cadr tickcheck))) mintickangulardif)
	)
      (setq
	dupfound
	 T
	templist
	 nil
      )
      (setq templist (cdr templist))
    )
  )
  (if (not dupfound)
    (cons tick ticklist)
    ticklist
  )
)
