Mais estacas de 20m

Então... voltando ao assunto das estacas de 20m, dá pra produzir o mesmo efeito usando as estacas formatadas para "station index format", como na "Figura 1", e me pareceu até mais prático fazer desta maneira... claro, que ao criar a "labels" dos alinhamentos, devemos configurar corretamente o Station Index Increment" como destacado na "Figura 2", digo que é mais fácil pois em todas as labels de estacas tem o "station index format", então é só configurar o "deafult increment", , assim o civil 3d assume este valor por padrão..De qualquer forma, o tutorial anterior fica valendo para demonstrar uma das utilidades das "Expressions"

Civil 3D e estacas de 20m


Como diria o Alotoni, do Jovem Nerd: Lambda, Lambda, Lambda Nerds!!!


Bom hoje um pouco de Cilvil 3d, só pra sair um pouco desse negócio de visual lisp!!


Gostou do título?, é isso mesmo!! estacas de 20m!! padrão DER, Brasil, essas paradas todas... mas e aí, como que faz??


O Civil 3d teima que "1+3,00m" é 103 metros e nós pobres brasileiros somos diferentes!!, sim nossas estacas tem 20m, logo "1+3,00m" quer dizer 23,00 ( vinte e três !!! ) metros... e pelo que eu vi em todos os foruns que entrei, todos perguntam como que faz e a maioria diz que não dá, que é impossível, ou que dá, mas não sabe como...


Então... depois de ver tanta gente pedindo isso eu também quiz saber como fazer... claro, foruns gringos não ajudam muito, lá as estacas tem 100m, hehehe


Tem rodeio de mais?? ótimo, então vamos ao que interessa: ESTACAS DE 20m!! um "tutô" bem despretencioso:


1º) abra o civil 3d, e clique "New", escolha na lista de templates: "_Autodesk Civil 3D (Metric) NCS Base.dwt", usei este template no tutorialpor ter as unidades em metros já configuradas




2º) agora, abra no Tool Space, o editor de estilos dos "Alignments" e escolha a opção selecionada, como na imagem, vamos criar uma "Expression"






(Clique com o botão direito do mouse para aparece o menu suspenso com o "New"...)
3º) Aqui no editor de expressões, preencha como a imagemSeria interessante clicar o help e ver o que cada botão faz... neste exemplo estou usando o parâmetro "Raw Station", que me fornece a distância em metros no alinhamento e estou usando a função (clique o botão "F(x)") FLOOR esta função nos retorna o o "máximo inteiro menor que x", assim floor(12.8)=12, sacam? ele não arredonda!! ele pega o maior numero inteiro que é menor que "X"assim, escreveremos a seguinte expressão:


FLOOR({Raw Station}/20)

no campo "Name" digite "estaca" e no campo "Description" escreveremos a descrição (que óbvio isso...)
4º) Clique em "OK" e teremos salvo a primeira expressão, precisamos agora uma que nos devolva o sub-componente do texto da estaca, isto é, já temos como escrever o "20" mas ainda não temos o "+3,00m" entende? Abra novamente o editor de expressões como mostrado no passo (2) e insira a seguinte expressão no campo "Expression":


FMOD({Raw Station},20)


Aqui, só precisamos calcular o resto da divisão por 20, é o que a função FMOD faz, no campo "Name", coloque "subestaca", clique "OK" e teremos a segunda expressão


5º) Agora, iremos criar o componente da "Major Station", isto é, as estacas inteiras, vaja a figura:





O texto do componente "Text" ficará assim: <[estaca(P0|RN|AP|Sn|OF)]>


6º) Já temos a "Major Station", vamos fazer a "Minor Station", o procedimento é idêntico ao descrito no passo anterior e o texto do componente "TEXT" da label ficará assim:
<[estaca(P0|RN|AP|Sn|OF)]>+<[subestaca(P2|RN|AP|Sn|OF)]>

7º)Já temos tudo o básico para desenhar um alinhamento qualquer!!


Claro, temos ainda de configurar os componentes "TEXT" das labels dos "Geometry Points" etc, mas o procedimento é idêntico ao anterior


Experimentemos desenhar qualquer coisa:





Veja que deixei os "Geometry Points" sem configurar para mostrar que realmente tenho estacas de 20m!!

É isso... Qualquer sugestão ou crítica será bem vinda!!!

lisps_dlls

Tá... vamos simplificar as coisas, vou postar uma vez só, hein!! alguns já me perguntaram por que postei as subrotinas uma de cada vez... bom... nem eu sei, enfim, TODAS as SUBROTINAS que uso nos meus programas estão neste pacote: lisps_dlls.zip sendo necessário têla carregada ao usar qualquer ROTINA aqui postada..
Isso simplifica as coisas, pois posso postar apenas a ROTINA, sendo que as SUBROTINAS estão neste pacote, e antes que alguem me pergunte: "e os fontes???", estão aqui no blog... basta procurar
Qualquer hora coloco a lista de subrotinas que estão no pacote, o que cada uma faz, a lista de argumentos e as saídas delas... mas isso fica pra outra hora...

ivp

Vou postar uma rotina que me livrou de alguns problemas com polilinhas várias vezes, uma rotina que inverte o sentido do caminhamento da polilinha... sim, tem duzias de programinhas por aí que fazem isso, mas os que eu vi (o do POSICAO, por exemplo) só desenham uma nova entidade, apagando a antiga... bem, esta reorganiza os vértices da polilinha, mantendo seu aspecto, espessuras e arcos (no caso de lwpolylines, mas em fim...
clique para ver o código
;uso do método vla-put-coordinates incrementado
(defun put-coordinates2 (ent pts / vla)
  (
setq pts (if (= "LWPOLYLINE" (dxf 0 ent))
              (
mapcar '3dto2d pts)
              pts)
        pts (apply 'append pts)
        vla (vlax-ename->vla-object (ename-of ent)))
  (
vla-put-coordinates vla  (lst2array pts vlax-vbDouble))
  (
vlax-release-object vla))

;é um saco ter de escrever isso em todos os programas... 
;transforma uma coordenada 3d em 2d... é, só isso...
(defun 3dto2d (pt)
  (
list (car pt) (cadr pt)))

;função inversa do "vlax-safearray->list"
(defun lst2array (lst tipo / tmp)
 (
vlax-safearray-fill
    (vlax-make-safearray
      tipo
      (cons 0 (1- (length lst))))
    lst))

;inverte uma polilinha sem mudar os "bulges" (arcos) e "widths"
(defun c:ivp (/ pts ent ss s pts tmp l lpt a b)
  (
tbn:error-init (list (list "cmdecho" 0) T))
  (
prompt "\nSelecione as polilinhas...\n")
  (
setq ss  (ssget '((0 . "*POLYLINE")))
        ivp:sentido (if ivp:sentido ivp:sentido "H")
        s   (initget "H A" 0)
        s   (getkword (strcat
            "\nEscolha o Sentido [Horário, Anti-horário] <"
            (cadr (assoc ivp:sentido
                     '(("H" "Horário")
                       (
"A" "Anti-horário"))) )
            ">"))
        s   (if s s ivp:sentido)
        ivp:sentido s
        s
   (= "H" s))
  (
repeat (if ss (sslength ss) 0)
    (
setq ent (ssname ss 0)
          pts (get-points-polig ent))
    (
ssdel ent ss)
    (
if (/= s (isclockwise pts))
      (
if (= "POLYLINE" (DXF 0 ENT))
        (
put-coordinates2 ent (reverse pts))
        (
progn
          (setq pts (entget ent)
                lpt (sub-list pts
                            (vl-position (assoc 10 pts) pts)
                            (
- (length pts)
                   (
vl-position
                 (assoc 42 (reverse pts))
                 (
reverse pts))
                   1))
                tmp nil)
          (
foreach x lpt
            (if (= 42 (car x))
              (
setq tmp (cons (reverse (cons x l))
                  tmp)
                    l   nil)
              (
setq l (cons x l))))
      (
setq a   (mapcar 'car tmp)
        b   (mapcar '(lambda (l) (list (cons 40 (cdr (assoc 41 l)))
                           (
cons 41 (cdr (assoc 40 l)))
                           (
cons 42 (* -1 (cdr (assoc 42 l))))))
                (
mapcar 'cdr tmp))
        tmp (mapcar 'cons a (append (cdr b) (list (car b)))))
          (
entmod
        (append
          (sub-list pts 0 (1- (vl-position (assoc 10 pts) pts)))
          (
apply 'append tmp)
          (
list (assoc 210 pts))))
          (
entupd ent)
          ))))
  (
tbn:error-restore))


Link(s) da(s) subrotina(s) usada(s):

dxf,
3dto2d,
ename-of,
lst2array,
tbn:error-init,
get-points-polig,
isclockwise,
put-coordinates2,
sub-list,
tbn:error-restore
Bom, quem viu percebeu que joguei umas sub-rotinas a mais no código... pra frente farei uso delas então é bom deixar elas à mão!!

get-lst-elmts

Uma rotina interessante do ponto de vista de como "forçar" algumas coisas em DCLs, neste caso, estou mostrando como usar um slider e algumas toggles para simular uma lista de multipla escolha, onde o número de elementos pode ser maior que o numero de toggles disponíveis
ver..
;|mostra um diálogo para você escolher elmers
  tit  ->  título, string
  maxl ->  numero máximo de linhas a serem mostradas,
           se omitido, assume o valor 15
  lstpresel  ->  lista de strings com os nomes dos elmer que
           devem estar pré selecionados|;
(defun update-lst-listelmts (val / n)
  (
setq n 0
        s val)
  (
repeat (min maxl qtd)
    (
setq elm (nth (+ n (- qtd maxl s)) listelmts)
          n   (1+ n)
          key (itoa n))
    (
set_tile (strcat "tx" key) elm)
    (
set_tile (strcat "tg" key)
              (
if (member elm lstpresel) "1" "0"))
    (
action_tile  (strcat "tg" key)
      (
strcat
        "(setq lstpresel (if (= \"1\" $value) (cons \""
        elm "\" lstpresel) (vl-remove \"" elm "\" lstpresel)))"))))

(
defun get-lst-layer (tit maxl lst)
  ;pegue a lista de elmers do desenho em ordem alfabetica:
  (get-lst-elmts tit (vl-sort (get-tableof "layers") '<) lst maxl))


(
defun get-lst-elmts  (tit listelmts lstpresel maxl / tmp file filename
                       dcl n  qtd elm key
)
;sub-rotina para atualizar a tela do diálogo
  (setq 
;cria um nome de arquivo temporário:
        filename        (vl-filename-mktemp "gll.dcl")
;cria o arquivo e abre ele para edição:
        file            (open filename "w")
        n               0
;se nao foi fornecido o numero de linhas, assume que sejam 15
        maxl            (if maxl maxl 15)
;quantidade de elmers no desenho:
        qtd             (length listelmts))
;inicia a criação do diálogo:
  (write-line
    (strcat "getlstelmer : dialog {width = 50; label = \""
            tit  "\";\n:row { :column {") file)
  ;escreve tantas linhas quanto fornecido pela variavel MAXL:
  (repeat (min maxl qtd)
    (
setq n (1+ n))
    (
write-line
      (strcat ":row { :toggle { key = \"tg" (itoa n)
              "\";} :text{ width=50; key = \"tx"
              (itoa n) "\";}}")
      file))
  ;finaliza a criação do dcl construindo os botões:
  (write-line
    (strcat "}\n"
      (if (> qtd maxl)
        (
strcat
          ":slider { key = \"s\"; min_value = 0;  max_value = "
          (itoa (- qtd maxl)) "; big_increment = "  (itoa maxl)
          "; layout = vertical;}")  "")
"} :row{ :button {key = \"ALL\"; label = \"Tudo\";}
:button {key = \"NEM\"; label = \"Nenhum\";} "
;botão ok:
":button {label = \"Ok\"; key=\"accept\";
is_default=true;}"
;botão cancel:
":button {label = \"Sair\"; key=\"cancel\";
is_cancel=true;}}}"
)
    file)
  ;fecha o arquivo, ele está pronto!
  (close file)
  ;carrega o arquivo DCL na memória do cad:
  (setq dcl (load_dialog filename)
        s   (- qtd maxl)) ;posição do slider...
  ;abre um quadro de diálogo:
  (new_dialog "getlstelmer" dcl)
  ;define as ações de cada elemento do diálogo...
  (action_tile "s" ;slider
    "(update-lst-listelmts (atoi $value))")
  (
action_tile  "ALL"
    "(progn (setq lstpresel listelmts)
         (update-lst-listelmts s))"
);botao todos
  (action_tile  "NEM"
    "(progn (setq lstpresel nil)
        (update-lst-listelmts s))"
);botão nenhum
;marca a posição do slider:
  (set_tile "s" (itoa s))
;atualiza o estados das toggles...:
  (update-lst-listelmts s)
;inicia o diálogo, e salva o resultado
  (setq lstpresel (if (= 1 (start_dialog)) lstpresel))
;descarrega o diálogo
  (unload_dialog dcl)
;apaga o dcl temporário que criamos
  (vl-file-delete filename)
  lstpresel)
Para usar é simples:
(get-lst-elmts
 "título" ;título
 '("1" "2" "3" "4" "5" "6" "7" "8" "9" "10") ;elementos
 '("5" "6");pré-selecionados
 5 ;numero maximo de linhas
)


Retornando a lista do elementos selecionados em caso de clicar OK e NIL em caso de clicar SAIR