introduction - documentation.help · introduction > working in visual lisp this tutorial assumes...

205
ntroduction This tutorial is designed to demonstrate several powerful capabilities of the AutoLISP ® programming environment for AutoCAD ® and introduce features of the AutoLISP language that may be new to you. The purpose of the tutorial is to draw a garden path using an automated drawing tool that minimizes drafting time and shows the power of parametric programming. You will learn to create a drawing routine that automates the generation of a complex shape—the kind of drafting operation you do not want to have to do manually over and over again. Topics in this section Working in Visual LISP Tutorial Overview Please send us your comment about this page

Upload: vuduong

Post on 02-Oct-2018

228 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Introduction

ThistutorialisdesignedtodemonstrateseveralpowerfulcapabilitiesoftheAutoLISP®programmingenvironmentforAutoCAD®andintroducefeaturesoftheAutoLISPlanguagethatmaybenewtoyou.

Thepurposeofthetutorialistodrawagardenpathusinganautomateddrawingtoolthatminimizesdraftingtimeandshowsthepowerofparametricprogramming.Youwilllearntocreateadrawingroutinethatautomatesthegenerationofacomplexshape—thekindofdraftingoperationyoudonotwanttohavetodomanuallyoverandoveragain.

Topicsinthissection

WorkinginVisualLISPTutorialOverview

Pleasesendusyourcommentaboutthispage

Page 2: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Introduction>

WorkinginVisualLISP

ThistutorialassumesyouhavesomefamiliaritywithLISPorAutoLISP.ItalsoassumesyouunderstandbasicWindows®filemanagementtaskssuchascreatingdirectories,copyingfiles,andnavigatingthroughthefilesystemonyourharddiskornetwork.IfyouneedaprimeronusingAutoCAD,pleaseexploretheUser’sGuideformoreinformation.

Inthistutorial

TheVisualLISP®(VLISP)environmentisintroduced.Thisenvironmentprovidesyouwithediting,debugging,andothertoolsspecifictothecreationofAutoLISPapplications.

ActiveX®andReactorfunctionsofAutoLISParedemonstrated,aswellasseveralotherextensionstotheAutoLISPlanguageprovidedwithVLISP.

Therearethefollowingtwopossibleexecutioncontextsforthistutorial:

TheapplicationmayberunasinterpretedLISPinpiecemealfilesand/orfunctionsthatareloadedintoasingledocument,or

TheprogramcodecanbecompiledintoaVLXapplication,denotedbya*.vlxexecutable.AVLXoperatesfromaself-containednamespacethatcaninteractwiththeapplication-loadingdocument.

Pleasesendusyourcommentaboutthispage

Page 3: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Introduction>

TutorialOverview

YourgoalinthistutorialistodevelopanewcommandforAutoCADthatdrawsagardenpathandfillsitwithcirculartiles.Thetutorialisdividedintosevenlessons.Asyouprogressfromlessontolesson,youreceiveprogressivelylessdetailedinstructionsonhowtoperformindividualtasks.HelpisavailableintheVLISPdocumentationifyouhaveanyquestions.

Lessons4and5areatanintermediatelevelandgobeyondbasicAutoLISPconcepts.Lessons6and7containadvancedandfairlycomplexprogrammingtasksandaredesignedforexperiencedAutoLISPdevelopers.

IfyouchosethefullinstallationoptionwhenyouinstalledAutoCAD,thesourcecodefilesareinthefollowingdirectory:

<AutoCADdirectory>\Tutorial\VisualLISP\

ItisrecommendedyoudonotmodifythesamplesourcecodefilessuppliedwithAutoCAD.Ifsomethingisnotworkingcorrectlywithinyourprogram,youmaywanttocopythesuppliedsourcecodeintoyourworkingdirectory.Throughoutthetutorial,theworkingdirectoryisreferredtoas:

<AutoCADdirectory>\Tutorial\VisualLISP\MyPath

Ifyouchooseadifferentpathforyourworkingdirectory,substituteyourdirectorynameattheappropriatetimes.

Pleasesendusyourcommentaboutthispage

Page 4: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DesigningandBeginningtheProgram

Inthisfirstlesson,you'llbeginbydefiningwhattheapplicationwilldo.UsingtheVisualLISP®(VLISP)developmentenvironment,you'llcreateaLISPfileandbeginwritingAutoLISP®codetosupportyourapplication.Intheprocess,you'llbegintodiscoverhowVLISPfacilitatesapplicationdevelopment.

Topicsinthissection

DefiningOverallProgramGoalsGettingStartedwithVisualLISPLookingatVisualLISPCodeFormattingAnalyzingtheCodeFillingtheGapsintheProgramLettingVisualLISPCheckYourCodeRunningtheProgramwithVisualLISPWrappingUpLesson1

Pleasesendusyourcommentaboutthispage

Page 5: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DesigningandBeginningtheProgram>

DefiningOverallProgramGoals

DevelopinganAutoLISPprogrambeginswithanideaforautomatingsomeaspectofAutoCAD®.Itmaybeaneedtospeeduparepetitivedraftingfunction,ortosimplifyacomplexseriesofoperations.Forthetutorial,thegardenpathyouwantyourprogramtodrawisacomplexshapewithavariablenumberofcomponents,basedoninitialinputfromtheuser.Here'swhatitwilllooklike:

Yourprogrammustdothefollowingtodrawthegardenpath:

Givenastartpoint,anendpoint,andawidth,drawarectilinearboundary.Theboundarycanbeatany2Dorientation.Thereshouldbenolimitonhowlargeorsmallitcanbe.

Prompttheuserfortilesizeandtilespacingvalues.Thetilesaresimplecirclesandwillfilltheboundarybutmustnotoverlaporcrosstheboundary.

Placethetilesinalternatingrows.

Page 6: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Toseehowthingsshouldwork,youcanrunacompletedversionoftheapplicationthatissuppliedwithAutoCAD.

Torunthesuppliedexample

1. FromtheAutoCADToolsmenu,chooseLoadApplication.

2. Selectgardenpath.vlxfromtheTutorial\VisualLISPdirectory,andchooseLoad.

3. ChooseClose.

4. AttheCommandprompt,entergpath.

5. RespondtothefirsttwopromptsbypickingastartpointandanendpointintheAutoCADdrawingarea.

6. Enter2atthehalf-widthofPathprompt.

7. ChooseOKwhenpromptedbytheGardenPathTileSpecificationsdialogbox.

Pleasesendusyourcommentaboutthispage

Page 7: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DesigningandBeginningtheProgram>

GettingStartedwithVisualLISP

Nowthatyou'veseenhowtheapplicationissupposedtowork,youcanbegindevelopingitwithVLISP.Butfirst,ithelpstodemonstratewhatcanhappenwhenVLISPiswaitingforcontroltoreturnfromAutoCAD.Youmayhavealreadyencounteredthis.

ToseeVisualLISPwaitforcontroltoreturnfromAutoCAD

1. FromtheAutoCADToolsmenu,chooseLoadApplication.

2. Selectgardenpath.vlxfromtheTutorial\VisualLISPdirectory,andchooseLoad.

3. ChooseClose.

4. AttheAutoCADCommandprompt,entervlisptostartVisualLISP.

5. SwitchbacktotheAutoCADwindow(eitherselectAutoCADfromthetaskbarorpressALT+TABandchooseAutoCAD),andentergpathattheAutoCADCommandprompt.

6. Beforerespondingtothepromptsfromgpath,switchbacktotheVLISPwindow.IntheVLISPwindow,themousepointerappearsasaVLISPsymbol,andyoucannotchooseanycommandsorentertextanywhereintheVLISPwindow.ThepointersymbolisareminderthatthereisanactivityyoumustcompleteinAutoCADbeforeresumingworkwithVLISP.RememberthiswheneveryouseetheVLISPpointer.

7. ReturntotheAutoCADwindowandrespondtoallthepromptsfromgpath.

Nowyouarereadytobeginbuildingthegardenpathapplication.

Page 8: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

TobeginapplicationdevelopmentwithVisualLISP

1. FromtheVLISPFilemenu,chooseNewFile.

2. Enterthefollowingcodeinthetexteditorwindow(itisthewindowtitled“<Untitled-0>”);youcanomitthecomments,ifyouwish:

;;;FunctionC:GPathisthemainprogramfunctionanddefinesthe

;;;AutoCADGPATHcommand.

(defunC:GPath()

;;Asktheuserforinput:firstforpathlocationand

;;direction,thenforpathparameters.Continueonlyifyouhave

;;validinput.

(if(gp:getPointInput);

(if(gp:getDialogInput)

(progn

;;Atthispoint,youhavevalidinputfromtheuser.

;;Drawtheoutline,storingtheresultingpolyline

;;"pointer"inthevariablecalledPolylineName.

(setqPolylineName(gp:drawOutline))

(princ"\nThegp:drawOutlinefunctionreturned<")

(princPolylineName)

(princ">")

(Alert"Congratulations-yourprogramiscomplete!")

)

(princ"\nFunctioncancelled.")

)

(princ"\nIncompleteinformationtodrawaboundary.")

)

(princ);exitquietly

)

;;;Displayamessagetolettheuserknowthecommandname.

(princ"\nTypegpathtodrawagardenpath.")

(princ)

3. ChooseFile SaveAsfromthemenu,andsavethecodeinthenewfileas<AutoCADdirectory>\Tutorial\VisualLISP\MyPath\gpmain.lsp.

4. Reviewyourwork.

Pleasesendusyourcommentaboutthispage

Page 9: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DesigningandBeginningtheProgram>

LookingatVisualLISPCodeFormatting

VLISPrecognizesthevarioustypesofcharactersandwordsthatmakeupanAutoLISPprogramfileandhighlightsthecharactersindifferentcolors.Thismakesiteasierforyoutospotsomethingincorrectquickly.Forexample,ifyoumissaclosingquotationmarkfollowingatextstring,everythingyoutypecontinuestodisplayinmagenta,thecolordenotingstrings.Whenyouentertheclosingquotationmark,VLISPcorrectlycolorsthetextfollowingthestring,accordingtothelanguageelementitrepresents.

Asyouentertext,VLISPalsoformatsitbyaddingspacingandindentation.TogetVLISPtoformatcodeyoucopyintoitstexteditorfromanotherfile,chooseTools FormatCodeinEditorfromtheVLISPmenu.

Pleasesendusyourcommentaboutthispage

Page 10: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DesigningandBeginningtheProgram>

AnalyzingtheCode

Thedefunfunctionstatementdefinesthenewfunction.NoticethemainfunctionisnamedC:GPath.TheC:prefixestablishesthatthisfunctioniscallablefromtheAutoCADcommandline.GPathisthenameusersentertolaunchtheapplicationfromtheAutoCADCommandprompt.Thefunctionsthatobtaininputfromusersarenamedgp:getPointInputandgp:getDialogInput.Thefunctionthatdrawsthegardenpathoutlineisgp:drawOutline.Thesenamesareprefixedwithgp:toindicatetheyarespecifictothegardenpathapplication.Thisisnotarequirement,butitisagoodnamingconventiontousetodistinguishapplication-specificfunctionsfromgeneralutilityfunctionsyoufrequentlyuse.

Inthemainfunction,princexpressionsdisplaytheresultsoftheprogramifitrunssuccessfully,orawarningmessageiftheprogramencountersanunexpectedevent.Forexample,aswillbeseeninLesson2,iftheuserpressesENTERinsteadofpickingapointonthescreen,thecalltogp:getPointInputendsprematurely,returninganilvaluetothemainfunction.Thiscausestheprogramtoissueaprincmessageof“Incompleteinformationtodrawaboundary.”

Thecalltoprincneartheendoftheprogramservesasaprompt.Uponapplicationload,thepromptinformsuserswhattheyneedtotypetoinitiatethedrawingofagardenpath.Thefinalprincwithoutastringargumentforcestheprogramtoexitquietly,meaningthevalueofthemainfunction'sfinalexpressionisnotreturned.Ifthefinalsuppressingprincwereomitted,thepromptwoulddisplaytwice.

Pleasesendusyourcommentaboutthispage

Page 11: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DesigningandBeginningtheProgram>

FillingtheGapsintheProgram

Forthecodeinthisnewfiletoworkcorrectly,youmustwritethreemorefunctiondefinitions.Themaingardenpathcodecontainscallstothreecustomfunctions:

gp:getPointInput

gp:getUserInput

gp:drawOutline

Fornow,youwilljustwritestubbed-outfunctiondefinitions.Astubbed-outfunctionservesasaplaceholderforthecompletefunctionthatistofollow.Itallowsyoutotryoutpiecesofyourcodebeforeaddingallthedetailneededtocompletetheapplication.

Todefinestubbed-outfunctionsfortheapplication

1. PositionyourcursoratthetopoftheprogramcodeinthetexteditorwindowandpressENTERacoupleoftimestoaddblanklines.

2. Enterthefollowingcode,beginningwhereyouinsertedtheblanklines:

;;;Functiongp:getPointInputwillgetpathlocationandsize

(defungp:getPointInput()

(alert

"Functiongp:getPointInputwillgetuserdrawinginput"

)

;;Fornow,returnT,asifthefunctionworkedcorrectly.

T

)

;;;Functiongp:getDialogInputwillgetpathparameters

(defungp:getDialogInput()

(alert

"Functiongp:getDialogInputwillgetuserchoicesthroughadialog"

)

Page 12: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

;;Fornow,returnT,asifthefunctionworkedcorrectly.

T

)

;;;Functiongp:drawOutlinewilldrawthepathboundary

(defungp:drawOutline()

(alert

(strcat"Thisfunctionwilldrawtheoutlineofthepolyline"

"\nandreturnapolylineentityname/pointer."

)

)

;;Fornow,simplyreturnaquotedsymbol.Eventually,this

;;functionwillreturnanentitynameorpointer.

'SomeEname

)

RightbeforetheendofeachinputfunctionisalineofcodethatcontainsonlyaT.Thisisusedasareturnvaluetothecallingfunction.AllAutoLISPfunctionsreturnavaluetothefunctionthatcalledthem.TheletterTisthesymbolfor“true”inAutoLISP,andaddingitcausesthefunctiontoreturnatruevalue.Thewaygpmain.lspisstructured,eachinputfunctionitcallsmustreturnavalueotherthannil(whichindicates“novalue”)fortheprogramtoproceedtothenextstep.

AnAutoLISPfunctionwill,bydefault,returnthevalueofthelastexpressionevaluatedwithinit.Inthestubbed-outfunctions,theonlyexpressionisacalltothealertfunction.Butalertalwaysreturnsnil.Ifthisisleftasthelastexpressioningp:getPointInput,itwillalwaysreturnnil,andyouwillneverpassthroughtheiftothegp:getDialogInputfunction.

Forasimilarreason,theendofthegp:DrawOutlinefunctionreturnsaquotedsymbol('SomeEname)asaplaceholder.AquotedsymbolisaLISPconstructthatisnotevaluated.(IfyouarecuriousabouthowtheLISPlanguageworks,thereareanumberofgoodbooksavailable,mentionedattheendofthistutorial.)

Pleasesendusyourcommentaboutthispage

Page 13: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DesigningandBeginningtheProgram>

LettingVisualLISPCheckYourCode

VLISPhasapowerfulfeatureforcheckingyourcodeforsyntacticalerrors.Usethistoolbeforetryingtoruntheprogram.Youcancatchcommontypingerrors,suchasmissingparenthesesormissingquotationmarks,andothersyntacticalproblems.

Tocheckthesyntaxofyourcode

1. Makesurethetexteditorwindowcontaininggpmain.lspistheactivewindow.(Clickinthetitlebarofthewindowtoactivateit.)

2. FromtheVLISPmenu,chooseTools CheckTextinEditor.

TheBuildOutputwindowisdisplayedwiththeresultsofthesyntaxcheck.IfVLISPdidnotdetectanyerrors,thewindowcontainstextsimilartothefollowing:

[CHECKINGTEXTGPMAIN.LSPloading...]

......

;Checkdone.

Ifyouhaveproblemsandneedhelp,refertothe“DevelopingProgramswithVisualLISP”sectionoftheAutoLISPDeveloper'sGuide.Seeifyoucandeterminewheretheproblemislocated.Ifyouarespendingtoomuchtimelocatingtheproblem,usethesamplegpmain.lspfileprovidedinthelesson1directorytocontinuewiththetutorial.

Tousethesuppliedgpmain.lspprogram(ifnecessary)

1. Closethetexteditorwindowcontainingthegpmain.lspcodeyouentered.

Page 14: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

2. ChooseFile OpenFilefromtheVLISPmenu,andopenthegpmain.lspfileinthe\Tutorial\VisualLISP\lesson1directory.

3. ChooseFile SaveAsandsavethefileinyour\Tutorial\VisualLISP\MyPathdirectoryasgpmain.lsp,replacingthecopyyoucreated.

Pleasesendusyourcommentaboutthispage

Page 15: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DesigningandBeginningtheProgram>

RunningtheProgramwithVisualLISP

RunningAutoLISPprogramsinVLISPallowsyoutousethemanydebuggingfeaturesofVLISPtoinvestigateproblemsthatmayoccurinyourapplication.

Toloadandruntheprogram

1. Withthetexteditorwindowactive,chooseTools LoadTextinEditorfromtheVLISPmenu.

2. Atthe_$promptintheVLISPConsolewindow,enter(C:GPath).TheConsolewindowexpectscommandstobeenteredinAutoLISPsyntax,soallfunctionnamesmustbeenclosedinparentheses.

3. PressENTERorclickOKinresponsetothemessagewindows.Thefinalmessageshouldread“Congratulations-yourprogramiscomplete!”

Note IfAutoCADisminimizedwhenyourungpath,youwillnotseethepromptsuntilyourestoretheAutoCADwindow(usingeitherthetaskbarorALT+TAB).

Pleasesendusyourcommentaboutthispage

Page 16: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DesigningandBeginningtheProgram>

WrappingUpLesson1

Inthislesson,you

Definedprogramgoals.

Learnedthevalueofstubfunctions.

Learnedaboutnamingfunctionstoidentifythemasspecifictoyourapplicationorasgeneralfunctionstobeusedoverandover.

LearnedhowtouseVLISPtocheckyourcode.

LearnedhowtoloadandrunaprograminVLISP.

Youaredonewiththislesson.Saveyourprogramfileagaintobecertainyouhavethelatestrevisions.

Pleasesendusyourcommentaboutthispage

Page 17: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools

ThislessonteachesyouhowtouseseveralvaluableVisualLISP®debuggingtoolsthatspeedupthedevelopmentofAutoLISP®programs.Youwillalsolearnthedifferencebetweenlocalandglobalvariables,andwhentousethem.Yourprogramwillbecomemoreactive—promptinguserstoentersomeinformation.Theinformationwillbestoredinalistandyou'llbegintounderstandthepowerofusinglistswithinyourAutoLISPprograms.Afterall,LISPgotitsnamebecauseitisaLIStProcessinglanguage.

Topicsinthissection

DifferentiatingBetweenLocalandGlobalVariablesUsingAssociationListstoBundleDataExaminingProgramVariablesRevisingtheProgramCodeCommentingProgramCodeSettingaBreakpointandUsingMoreWatchesWrappingUpLesson2

Pleasesendusyourcommentaboutthispage

Page 18: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>

DifferentiatingBetweenLocalandGlobalVariables

Thislessondiscussestheuseoflocalvariablesversusglobaldocumentvariables.Globalvariablesareaccessiblebyallfunctionsloadedwithinadocument(anAutoCAD®drawing).Thesevariablesmayretaintheirvalueaftertheprogramthatdefinedthemcompletes.Sometimes,thisiswhatyouwant.You'llseeanexampleofthislaterinthetutorial.

Localvariablesretaintheirvalueonlyaslongasthefunctionthatdefinedthemisrunning.Afterthefunctionfinishesrunning,thelocalvariablevaluesareautomaticallydiscarded,andthesystemreclaimsthememoryspacethevariableused.Thisisknownasautomaticgarbagecollection,andisafeatureofmostLISPdevelopmentenvironments,suchasVLISP.Localvariablesusememorymoreefficientlythanglobalvariables.

Anotherbigadvantageisthatlocalvariablesmakeiteasiertodebugandmaintainyourapplications.Withglobalvariables,youareneversurewhenorinwhichfunctionthevariable'svaluemightbemodified;withlocalvariablesyoudon'thaveasfartotrace.Youusuallyendupwithfewersideeffects(thatis,one

Page 19: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

partoftheprogramaffectingavariablefromanotherpartoftheprogram).

Becauseoftheadvantagescited,thistutorialuseslocalvariablesalmostexclusively.

Note IfyouhavebeenworkingwithAutoLISPforsometime,youmayhavedevelopedthepracticeofusingglobalvariablesduringdevelopmenttoexamineyourprogramwhileyouarebuildingit.Thispracticeisnolongernecessary,giventhepowerfuldebuggingtoolsofVLISP.

Topicsinthissection

UsingLocalVariablesintheProgramExaminingthegp:getPointInputFunction

Pleasesendusyourcommentaboutthispage

Page 20: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>DifferentiatingBetweenLocalandGlobalVariables>

UsingLocalVariablesintheProgram

Refertothegp:getPointInputfunctionyoucreatedinLesson1:

(defungp:getPointInput()

(alert

"Functiongp:getPointInputwillgetuserdrawinginput"

)

;;Fornow,returnT,asifthefunctionworkedcorrectly.

T

)

Sofar,thefunctiondoesnotdomuchwork.Youwillnowbegintobuildonitbyaddingfunctionstogetinputfromtheuser,whichwilldefinethestartpoint,endpoint,andwidthofthepath.

ItisagoodpracticewhencreatingAutoLISPprogramstoemulatethebehaviorofAutoCAD.Forthisreason,insteadofaskingtheusertoindicatethewidthbyselectingapointinthedrawinginrespecttothecenterlineofalinearshape,yourprogramshouldaskforaselectionofthehalf-width.

Oncethegp:getPointInputfunctioniscomplete,thevariables,aswellasthevaluesassignedtothem,willnolongerexist.Therefore,youwillstoreuser-suppliedvaluesinlocalvariables.Here'swhatthefunctionmightlooklike:

(defungp:getPointInput(/StartPtEndPtHalfWidth)

(if(setqStartPt(getpoint"\nStartpointofpath:"))

(if(setqEndPt(getpointStartPt"\nEndpointofpath:"))

(if(setqHalfWidth(getdistEndPt"\nhalf-widthofpath:"))

T

)

)

)

)

Thelocalvariablesaredeclaredfollowingtheslashcharacter,inthedefun

Page 21: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

statementthatbeginsthefunction.Thefirstcalltogetpointpromptstheusertoindicateastartpoint.Theendpointisthenacquiredinrelationtothechosenstartpoint.Whileselectingtheendpoint,theuserwillobservearubber-bandlineextendingfromthestartpoint.Similarly,whilesettingthehalf-widthvalue,theuserwillviewanotherrubber-bandline,thistimerepresentingdistance,emanatingfromtheendpoint.

Toseehowgp:getPointInputworks

1. Typethegp:getPointInputcodeintotheVLISPConsolewindow.

2. WiththeConsolewindowcursorfollowingthelastparenthesisoftheblockofcode(oronthenextlinebelowit),pressENTERandyouwillreplaceanypreviouslyloadedversionofthegp:getPointInputfunction.

3. ExecutethefunctionfromtheConsolewindowbyentering(gp:getPointInput)attheConsoleprompt.

4. Pickpointswhenprompted,andenterahalf-widthvalue.

Pleasesendusyourcommentaboutthispage

Page 22: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>DifferentiatingBetweenLocalandGlobalVariables>

Examiningthegp:getPointInputFunction

Whenyouranthegp:getPointInputfunction,controlwasautomaticallypassedfromVLISPtoAutoCAD.Yourespondedtothreeprompts,afterwhichcontrolwaspassedbackfromAutoCADtoVLISP,andaTsymboldisplayedintheConsolewindow.

Withintheprogram,here'swhathappens:

1. VLISPwaitsforyoutopickthefirstpoint.

2. Whenyoupickthefirstpoint,theprogramstoresthevalueofyourselection(alistcontainingthreecoordinatevalues—anX,Y,andZvalue)intotheStartPtvariable.

3. Thefirstiffunctionexaminestheresulttodeterminewhetheravalidvaluewasenteredornovaluewasentered.Whenyoupickastartpoint,controlispassedtothenextgetpointfunction.

4. Whenyoupickanendpoint,thepointvalueisstoredintheEndptvariable.

5. Theresultofthisstatementisexaminedbythenextifstatement,andcontrolispassedtothegetdistfunction.

6. Thegetdistfunctionactsinasimilarfashionwhenyoupickapointonthescreenorenteranumericvalue.TheresultofthegetdistfunctionisstoredintheHalfWidthvariable.

7. ProgramflowreachestheTnesteddeeplywithinthefunction.Nootherfunctionsfollowthis,sothefunctionends,andthevalueTisreturned.ThisistheTyouseeattheConsolewindow.

Youneedsomewaytoreturnvaluesfromonefunctiontoanother.Onewayto

Page 23: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

dothisistocreatealistofthevaluesretrievedfromgp:getPointInput,ashighlightedinthefollowingcode:

(defungp:getPointInput(/StartPtEndPtHalfWidth)

(if(setqStartPt(getpoint"\nStartpointofpath:"))

(if(setqEndPt(getpointStartPt"\nEndpointofpath:"))

(if(setqHalfWidth(getdistEndPt"\nhalf-widthofpath:"))

(listStartPtEndPtHalfWidth)

)

)

)

)

Copythisversionofgp:getPointInputintotheConsolewindowandpressENTER.Here'sanopportunitytotryanotherfeatureoftheConsolewindow.

TousetheConsolewindowhistoryfeaturetorungp:getPointInput

1. PressTAB.ThisinvokestheConsolehistorycommand,cyclingthroughanycommandspreviouslyenteredintheConsolewindow.Ifyougotoofar,pressSHIFT+TABtocycleintheotherdirection.

2. Whenyousee(gp:getPointInput)attheConsoleprompt,pressENTERtoexecutethefunctiononceagain.

3. Respondtothepromptsasbefore.

Thefunctionreturnsalistcontainingtwonestedlistsandareal(floatingpoint)value.Thereturnvalueslooklikethefollowing:

((4.462074.623180.0)(7.666884.623180.0)0.509124)

ThesevaluescorrespondtotheStartPt,EndPt,andHalfWidthvariables.

Pleasesendusyourcommentaboutthispage

Page 24: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>

UsingAssociationListstoBundleData

Thepreviousexampleworks,butyoucandobetter.Inthenextexercise,youwillbuildanassociationlist,orassoclist(aftertheLISPfunctionthatdealswithassociationlists).Inanassociationlist,thevaluesyouareinterestedinareassociatedwithkeyvalues.Hereisasampleassociationlist:

((104.462074.623180.0)(117.666884.623180.0)(40.1.018248))

Inthesampleassociationlist,thekeyvaluesarethenumbers10,11,and40.Thesekeyvaluesserveasauniqueindexwithinthelist.ThisisthemechanismAutoCADusestoreturnentitydatatoAutoLISPifyouaccessanentityfromwithinyourprogram.Akeyvalueof10indicatesastartpoint,akeyvalueof11istypicallyanendpoint.

Whataretheadvantagesofanassociationlist?Foronething,unliketheregularlist,theorderofthevaluesreturneddoesnotmatter.Lookatthefirstlistagain:

((4.462074.623180.0)(7.666884.623180.0)0.509124)

Lookatthereturnvalues;itisnotapparentwhichsublististhestartpointandwhichistheendpoint.Furthermore,ifyoumodifythefunctioninthefuture,anyotherfunctionthatreliesondatareturnedinaspecificordermaybeadverselyaffected.

Usinganassociationlist,theorderofthevaluesdoesnotmatter.Iftheorderofanassociationlistchanges,youcanstilltellwhichvaluedefineswhat.Forexample,an11valueisstillanendpoint,regardlessofwhereitoccurswithintheoveralllist:

((117.666884.623180.0);orderoflist

(40.1.018248);hasbeen

(104.462074.623180.0));modified

Page 25: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Topicsinthissection

PuttingAssociationListstoUseStoringtheReturnValueofgp:getPointInputinaVariable

Pleasesendusyourcommentaboutthispage

Page 26: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>UsingAssociationListstoBundleData>

PuttingAssociationListstoUse

Whenyouuseassociationlists,youshoulddocumentwhatyourkeyvaluesrepresent.Forthegardenpath,thekeyvaluesof10,11,40,41,and50willmeanthefollowing:

10indicatesthe3Dcoordinateofthestartpointofthepath.

11indicatesthe3Dcoordinateoftheendpointofthepath.

40indicatesthewidth(notthehalf-width)ofthepath.

41indicatesthelengthofthepath,fromstarttoend.

50indicatestheprimaryvector(orangle)ofthepath.

Thefollowingisanupdatedversionofthegp:getPointInputfunction.Withinit,anAutoLISPfunctioncalledcons(shortforconstructalist)buildsthekeyedsubliststhatbelongtotheassociationlist.CopythisversiontotheConsolewindow,pressENTER,andrun(gp:getPointInput)again:

(defungp:getPointInput(/StartPtEndPtHalfWidth)

(if(setqStartPt(getpoint"\nStartpointofpath:"))

(if(setqEndPt(getpointStartPt"\nEndpointofpath:"))

(if(setqHalfWidth(getdistEndPt"\nhalf-widthofpath:"))

;;ifyou'vemadeitthisfar,buildtheassociationlist

;;asdocumentedabove.Thiswillbethereturnvalue

;;fromthefunction.

(list

(cons10StartPt)

(cons11EndPt)

(cons40(*HalfWidth2.0))

(cons50(angleStartPtEndPt))

(cons41(distanceStartPtEndPt))

)

)

)

)

Page 27: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

)

Noticethat,whenbuildingthelist,theprogramconvertsthehalf-widthspecifiedbytheuserintoafullwidthbymultiplyingitsvalueby2.

TheConsolewindowshowsoutputsimilartothefollowing:

_$(gp:getPointInput)((102.160981.601160.0)(1112.71267.119630.0)(40.0.592604)(50.0.481876)(41.11.9076))

_$

Pleasesendusyourcommentaboutthispage

Page 28: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>UsingAssociationListstoBundleData>

StoringtheReturnValueofgp:getPointInputinaVariable

Nowtrysomethingelse.Callthefunctionagain,butthistimestorethereturnvalueinavariablenamedgp_PathData.Todothis,enterthefollowingattheConsolewindowprompt:

(setqgp_PathData(gp:getPointInput))

Toviewthevalueofthevariableyoujustset,enteritsnameattheConsolewindowprompt:

_$gp_PathData

VLISPreturnsdatalikethefollowing:

((102.177421.157710.0)(1113.20577.004660.0)(40.1.12747)(50.0.487498)(41.12.4824))

Pleasesendusyourcommentaboutthispage

Page 29: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>

ExaminingProgramVariables

VLISPprovidesyouwithanentiretoolkitofprogramminganddebuggingtools.OneofthemostvaluabletoolsisaWatch,whichletsyouexaminevariablesinmoredetailthanappearsintheVLISPConsolewindow.Youcanalsowatchlocalvariableswithinfunctionsasthefunctionexecutes.

Towatchthevalueofavariable

1. ChooseDebug AddWatchfromtheVLISPmenu.VLISPdisplaysadialogboxtitled“AddWatch.”

Enterthenameofthevariableyouwishtoexamine.Forthisexample,specifygp_PathData,thevariableyoujustsetfromtheConsolewindow.VLISPdisplaysaWatchwindow:

VLISPdisplaysthevalueofthevariableonasinglelinewithintheWatchwindow—thebasewindowshownintheillustration.Inthiscase,thevalueofthevariableisalonglist,andyoucannotseeitsentirevalue.YoucanresizetheWatchwindowbydraggingitsborder,butthereisabetteralternative.

2. Double-clickonthevariablenameintheWatchwindow.ThisopensanInspectwindow:

Page 30: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

TheInspectwindowindicatesthedatatypeofthevariableyouareinspecting(inthiscase,alist),andthevalueofthevariable.Forlists,Inspectdisplayseachlistitemonitsownline.

3. Double-clickonthelinewiththeassociationlistkey11.VLISPopensanotherInspectwindow:

4. Whenyouaredoneinspectingvariables,closealltheInspectwindowsbutkeeptheWatchwindowopen.

Pleasesendusyourcommentaboutthispage

Page 31: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>

RevisingtheProgramCode

Nowthatyou'veseenhowtouseassociationlistsinAutoLISPcode,youcanusethismethodinwritingthecompletedversionofthegp:getPointInputfunction.Usingthefollowingcode,replaceormodifytheversionofgp:getPointInputyoupreviouslysavedingpmain.lsp.

Note Ifyouneedorwanttotypethecodeintogpmain.lsp,ratherthancopyitfromanotherfile,youcansavetimebyleavingoutthecomments(alllinesthatbeginwithsemicolons).Butdon'tgetusedtotheideaofwritingcodewithoutcomments!

;;;--------------------------------------------------------------;

;;;Function:gp:getPointInput;

;;;--------------------------------------------------------------;

;;;Description:Thisfunctionaskstheusertoselectthree;

;;;pointsinadrawing,whichwilldeterminethe;

;;;pathlocation,direction,andsize.;

;;;--------------------------------------------------------------;

;;;Iftheuserrespondstothegetfunctionswithvaliddata,;

;;;usestartPtandendPttodeterminetheposition,length,;

;;;andangleatwhichthepathisdrawn.;

;;;--------------------------------------------------------------;

;;;Thereturnvalueofthisfunctionisalistconsistingof:;

;;;(10.StartingPoint);;Listof3reals(apoint)denoting;

;;;;;startingpointofgardenpath.;

;;;(11.EndingPoint);;Listof3reals(apoint)denoting;

;;;;;endingpointofgardenpath.;

;;;(40.Width);;Realnumberdenotingboundary;

;;;;;width.;

;;;(41.Length);;Realnumberdenotingboundary;

;;;;;length.;

;;;(50.PathAngle);;Realnumberdenotingtheangle;

;;;;;ofthepath,inradians.;

;;;--------------------------------------------------------------;

(defungp:getPointInput(/StartPtEndPtHalfWidth)

(if(setqStartPt(getpoint"\nStartpointofpath:"))

(if(setqEndPt(getpointStartPt"\nEndpointofpath:"))

Page 32: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(if(setqHalfWidth(getdistEndPt"\nhalf-widthofpath:"))

;;ifyou'vemadeitthisfar,buildtheassociationlist

;;asdocumentedabove.Thiswillbethereturnvalue

;;fromthefunction.

(list

(cons10StartPt)

(cons11EndPt)

(cons40(*HalfWidth2.0))

(cons50(angleStartPtEndPt))

(cons41(distanceStartPtEndPt))

)))))

Next,youneedtoupdatethemainfunction,C:GPath,ingpmain.lsp.Modifyittolooklikethefollowingcode:

(defunC:GPath(/gp_PathData)

;;Asktheuserforinput:firstforpathlocationand

;;direction,thenforpathparameters.Continueonlyifyou

;;havevalidinput.Storethedataingp_PathData.

(if(setqgp_PathData(gp:getPointInput))

(if(gp:getDialogInput)

(progn

;;Atthispoint,youhavevalidinputfromtheuser.

;;Drawtheoutline,storingtheresultingpolyline

;;pointerinthevariablecalledPolylineName.

(setqPolylineName(gp:drawOutline))

(princ"\nThegp:drawOutlinefunctionreturned<")

(princPolylineName)

(princ">")

(Alert"Congratulations-yourprogramiscomplete!")

);_endofprogn

(princ"\nFunctioncancelled.")

);_endofif

(princ"\nIncompleteinformationtodrawaboundary.")

);_endofif

(princ) ;exitquietly

);_endofdefun

Ifyouarecopyingandpastingthecode,addthefollowingcommentsasaheaderprecedingC:GPath:

;;;**************************************************************;

;;;Function:C:GPathTheMainGardenPathFunction;

;;;--------------------------------------------------------------;

;;;Description:Thisisthemaingardenpathfunction.Itisa;

;;;C:function,meaningthatitisturnedintoan;

;;;AutoCADcommandcalledGPATH.Thisfunction;

;;;determinestheoverallflowofthegardenpath;

Page 33: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

;;;program.;

;;;**************************************************************;

;;;Thegp_PathDatavariableisanassociationlistoftheform:;

;;;(10.StartingPoint)-Listof3reals(apoint)denoting;

;;;startingpointofthegardenpath.;

;;;(11.EndingPoint)-Listof3reals(apoint)denoting;

;;;endpointofthegardenpath.;

;;;(40.Width)-Realnumberdenotingboundary;

;;;width.;

;;;(41.Length)-Realnumberdenotingboundary;

;;;length.;

;;;(50.PathAngle)-Realnumberdenotingtheangleof;

;;;thepath,inradians.;

;;;(42.TileSize)-Realnumberdenotingthesize;

;;;(radius)ofthegardenpathtiles.;

;;;(43.TileOffset)-Spacingoftiles,bordertoborder.;

;;;(3.ObjectCreationStyle);

;;;-Objectcreationstyleindicateshow;

;;;thetilesaretobedrawn.The;

;;;expectedvalueisastringandone;

;;;oneofthreevalues(stringcase;

;;;isunimportant):;

;;;"ActiveX";

;;;"Entmake";

;;;"Command";

;;;(4.PolylineBorderStyle);

;;;-Polylineborderstyledetermines;

;;;thepolylinetypetobeusedfor;

;;;pathboundary.Theexpectedvalue;

;;;oneofthefollowing(stringcaseis;

;;;unimportant):;

;;;"Pline";

;;;"Light";

;;;**************************************************************;

Totestthecoderevisions

1. Savetheupdatedfile.

2. UsetheCheckfeaturetosearchforanysyntacticalerrors.

3. Formatthecode,tomakeitmorereadable.

4. Loadthecode,sothatVLISPredefinestheearlierversionsofthefunctions.

5. Toruntheprogram,enter(c:gpath)attheConsoleprompt.

Page 34: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Iftheprogramdoesnotrunsuccessfully,tryfixingitandrunningitagain.Repeatuntilyouaretoofrustratedtocontinue.Ifallelsefails,youcancopythecorrectcodefromtheTutorial\VisualLISP\Lesson2directory.

Pleasesendusyourcommentaboutthispage

Page 35: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>

CommentingProgramCode

VLISPtreatsanyAutoLISPstatementbeginningwithasemicolonasacomment.Thelasttwocodeexamplescontainedalotofcomments.AcommentinanAutoLISPprogramissomethingyouwriteforyourself,notfortheprogram.Commentingcodeisoneofthebestprogrammingpracticesyoucanestablishforyourself.Whywritecomments?

Toexplainthecodetoyourselfwhenyouareeditingtheprogramninemonthsinthefuture,addingallthosefeaturesyourusershavebeenaskingyouabout.Memoryfades,andthemostapparentsequenceoffunctionscaneasilyturnintoanunrecognizabletangleofparentheses.

Toexplainthecodetootherswhoinherittheresponsibilityofupdatingtheprogram.Readingsomeoneelse'scodeisanextremelyfrustratingexperience,especiallyifthecodecontainsveryfewcomments.

VLISPcontainssomeutilitiesthathelpyouasyoucommentyourcode.Noticesomecommentsintheexamplesbeginwiththreesemicolons(;;;),sometimestwo(;;),andsometimesjustone(;).Referto“ApplyingVisualLISPCommentStyles”intheAutoLISPDeveloper'sGuidetoseehowVLISPtreatsthedifferentcomments.

Tosavespace,theremainingcodeexamplesinthistutorialdonotincludeallthecommentsinthesamplesourcefiles.Itisassumedyouhavealreadyestablishedthebeneficialhabitofextensivecommentingandwilldosowithoutanyprompting.

Pleasesendusyourcommentaboutthispage

Page 36: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>

SettingaBreakpointandUsingMoreWatches

Abreakpointisasymbol(point)youplaceinsourcecodetoindicatewhereyouwantaprogramtostopexecutingtemporarily.Whenyourunyourcode,VLISPproceedsnormallyuntilitencountersabreakpoint.Atthatpoint,VLISPsuspendsexecutionandwaitsforyoutotellitwhattodo.Ithasn'thaltedtheprogramforgood—ithasplaceditinastateofsuspendedanimation.

Whileyourprogramissuspended,youcan

Stepthroughyourcode,functionbyfunction,orexpressionbyexpression.

Resumenormalexecutionofyourprogramatanypoint.

Alterthevalueofvariablesdynamically,andchangetheresultsoftheprogrambeingexecuted.

AddvariablestotheWatchwindow.

Topicsinthissection

UsingtheDebugToolbarSteppingThroughCodeWatchingVariablesAsYouStepThroughaProgramSteppingOutofthegp:getPointInputFunctionandintoC:Gpmain

Pleasesendusyourcommentaboutthispage

Page 37: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>SettingaBreakpointandUsingMoreWatches>

UsingtheDebugToolbar

TheDebugtoolbarcontainsseveraltoolsyouwillemployasyouworkthroughthissection.Bydefault,thistoolbarisattachedtotheViewandToolstoolbars,andappearsasasingleVLISPtoolbar.

TheDebugtoolbaristheleft-mostsetoficons.Mostoftheitemsonthetoolbarareinactiveuntilyourunyourprogramindebuggingmode(thatis,withoneormorebreakpointsdefined).

Ifyouhaven'tdonesoalready,detachtheDebugtoolbarfromitspositionatthetopofthescreen.Todothis,grabanddragitbythetwoverticalgripsattheleftofthetoolbar.YoucandetachanyoftheVLISPtoolbarsandpositionthemonyourscreenwheretheyaremosteffectiveforyourstyleofwork.

TheDebugtoolbarisdividedintothreemaingroupsofbuttons,eachconsistingofthreebuttons.Whenyourunaprogramindebuggingmode,thetoolbarlookslikethefollowing:

Thefirstthreebuttonsallowyoutostepthroughyourprogramcode.

ThenextthreebuttonsdeterminehowVLISPshouldproceedwheneverithasstoppedatabreakpointoranerror.

Thenextthreebuttonssetorremoveabreakpoint,addaWatch,andjumptothepositionwithinyoursourcecodewherethelastbreakoccurred.

ThelastbuttonontheDebugtoolbarisaStepIndicator.Itdoesnotexecuteanyfunctionbutprovidesavisualindicationofwhereyourcursorispositionedasyoustepthroughyourcode.Whenyouarenotrunningindebuggingmode,this

Page 38: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

buttonappearsblank.

Tosetabreakpoint

1. IntheVLISPeditorwindowcontaininggpmain.lsp,positionyourcursorjustinfrontoftheopeningparenthesisofthesetqfunctionofthefollowinglineofcode,withinthegp:getPointInputfunction:

(setqHalfWidth(getdistEndPt"\nhalf-widthofpath:"))

2. Clickthemouseonce.Thepositionisillustratedinthefollowingscreensnapshot:

3. Withthetextinsertionpointset,choosetheToggleBreakpointbuttonontheDebugtoolbar.

TheToggleBreakpointbuttonactsasatoggle,alternatingbetweenonandoffstates.Ifthereisnobreakpointatthecursorposition,itsetsone;ifthereisalreadyabreakpointthere,itremovesit.

4. ChoosetheLoadActiveEditWindowbuttonontheToolstoolbartoloadthefile.

Page 39: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

5. Runthe(C:GPath)functionfromtheVLISPConsoleprompt.VLISPexecutestheprogramnormallyuptothebreakpoint.Inthiscase,itwillpromptyouforthefirsttwopoints—thestartpointandendpointofthepath.

6. Specifythestartpointandendpointwhenprompted.Afteryouspecifythepoints,VLISPsuspendsexecutionoftheprogramandreturnsfocustothetexteditorwindow,highlightingthelineofcodeatthebreakpointposition:

Thereareacoupleofthingstonotice:

Thecursorislocatedrightatthebreakpoint.Thismaybedifficulttonotice,soVLISPprovidesanotherclue.

IntheDebugtoolbar,theStepIndicatoricondisplaysaredI-beamcursorinfrontofapairofparentheses.ThisindicatestheVLISPdebuggerisstoppedbeforetheexpression.

Page 40: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Pleasesendusyourcommentaboutthispage

Page 41: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>SettingaBreakpointandUsingMoreWatches>

SteppingThroughCode

Therearethreebuttonsyoucanusetostepthroughyourcode.Thesearethethreeleft-mosticonsontheDebugtoolbar.Insequence,theyrepresentthefollowingactions:

Stepintothehighlightedexpression.

Stepovertotheendofthehighlightedexpression.

Stepouttotheendofthefunctionwhereyouarecurrentlystopped.

Beforeyoumakeaselection,takeanotherlookatthestatusofthehighlightedcode,thecursorposition,andtheStepIndicatorbutton.Insummary:anexpressionishighlighted,consistingofagetdistfunctionnestedwithinasetqfunction,andthecursorispositionedattheverybeginningofthehighlightedblock.

Tostepthroughthecodefromthebreakpoint

1. ChoosetheStepOverbutton.

AfteryouchoosetheStepOverbutton,controlpassestoAutoCADandyouarepromptedtospecifythewidthofthepath.

2. Replytotheprompt.Afteryouspecifythewidth,controlpassesbacktoVLISP.Noticewhereyourcursorisandwhatthestepindicatorbuttonshows.VLISPevaluatestheentirehighlightedexpression,thenstopsattheendoftheexpression.

3. ChoosetheStepOverbuttonagain.VLISPjumpstothebeginningofthe

Page 42: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

nextblockofcode,andhighlightstheentireblock.

4. ChoosetheStepInto(notStepOver)button.

Note Duringthisexercise,ifyoumakeanincorrectselectionandskipasteportwo,youcanrestarttheexerciseveryeasily.First,choosetheResetbuttonfromtheDebugtoolbar.ThisterminatestheexecutionofanyVLISPcode,andresetstheVLISPsystemtothetoplevel.Next,startoveratstep1.

Nowthefirstconsfunctionishighlighted,andVLISPisstoppedrightbeforethefunction(noticetheStepIndicatorbutton).

Pleasesendusyourcommentaboutthispage

Page 43: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>SettingaBreakpointandUsingMoreWatches>

WatchingVariablesAsYouStepThroughaProgram

Whileyoustepthroughyourprogram,youcanaddvariablestotheWatchwindowandchangetheirvalues.

IfyoudonotseetheWatchwindow,simplychoosetheWatchWindowbuttononthetoolbartobringitback.

IfyourWatchwindowstillscontainsthevariablegp_PathData,choosetheClearWindowbuttondisplayedatthetopoftheWatchwindow.

ToaddvariablestotheWatchwindow

1. Double-clickonanyoccurrenceofStartPtintheVLISPtexteditorwindow.Thisisthenameofthevariablewhosevalueyouwanttotrack.

2. ChoosetheAddWatchbuttonintheWatchwindow,orright-clickandchooseAddWatch.

3. RepeatthisprocessforthevariablesEndPtandHalfWidth.YourWatchwindowshouldresemblethefollowing:

Ifyouaredebuggingaprogramthatisn'tworkingcorrectly,usebreakpointsincombinationwithwatchestomakesureyourvariablescontainthevaluesyouexpect.

Page 44: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Ifavariabledoesnotcontainthevalueyouthinkitshould,youcanchangethevalueandseehowitaffectstheprogram.Forexample,saythatyouexpectthehalfwidthvaluetobeawholenumber.Butbecauseyouweren'tcarefulaboutpickingthepointsduringtheinputselections,youendedupwithavaluelike1.94818.

Tochangethevalueofavariablewhiletheprogramisrunning

1. EnterthefollowingattheConsoleprompt:

(setqhalfwidth2.0)

NotethatthevalueintheWatchwindowchanges.Butcanyoubesurethenewvaluewillbeusedwhenthewidthsublist(40.width)iscreatedintheassociationlist?AddonemoreexpressiontotheWatchwindowtotestthis.

2. ChooseDebug WatchLastEvaluationfromtheVLISPmenu.Thisaddsavariablenamed*Last-Value*toyourWatchwindow.*Last-Value*isaglobalvariableinwhichVLISPautomaticallystoresthevalueofthelastexpressionevaluated.

3. Stepthroughtheprogram(choosingeithertheStepIntoorStepOverbutton)untiltheexpressionresponsibleforbuildingthewidthsublistisevaluated.Thecodeforthisactionis:

(cons40(*HalfWidth2.0))

IfyouoverrodethevalueofHalfWidthasspecified,theevaluationofthisexpressionshouldreturn(40.4.0)intheWatchwindow.

Pleasesendusyourcommentaboutthispage

Page 45: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>SettingaBreakpointandUsingMoreWatches>

SteppingOutofthegp:getPointInputFunctionandintoC:Gpmain

Thereisonemorepointtoillustrate:whathappenstothevalueofthelocalvariablesingp:getPointInputafteryouexitthefunction.

Toexitgp:getPointInputandreturncontroltoc:gpath

1. ChoosetheStepOutbutton.

VLISPstepstotheveryendofthegp:getPointInputfunctionandstopsjustbeforeexiting.

2. ChoosetheStepIntobutton.

Controlreturnstoc:gpmain,thefunctionthatcalledgp:getPointInput.

ExaminethevaluesofthevariablesintheWatchwindow.Becausetheyarevariableslocaltothegp:getPointInputfunction,endptandStartPtarenil.VLISPautomaticallyreclaimedthememoryoccupiedbythesevariables.Normally,thethirdlocalfunctionvariableHalfWidthalsocontainsavalueofnil,butduetodebuggingactivity,itwasoverriddengloballyintheConsolewindowandstillpossessesthevalue2.0intheWatchwindow.Alsotheglobal*Last-Value*variabledisplaystheassociationlistconstructedbygp:getPointInput.

Yourfirstdebuggingsessioniscomplete.Butdon'tforgetyourprogramisstillinsuspendedanimation.

Page 46: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Tocompletethislesson

1. ChoosetheContinuebuttonontheDebugtoolbar.Respondtotheprompts.Thisrunstheprogramtocompletion.

2. ChooseDebug ClearAllBreakpointsfromtheVLISPmenu.Respond“yes”totheprompt.Thisremovesallthebreakpointswithinyourcode.Remember:youcanremoveindividualbreakpointsbypositioningthecursoratthebreakpointandchoosingtheToggleBreakpointbutton.

Pleasesendusyourcommentaboutthispage

Page 47: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

UsingVisualLISPDebuggingTools>

WrappingUpLesson2

Inthislesson,you

Learnedaboutlocalandglobalvariables.

Setandremovedbreakpointsinaprogram.

Steppedthroughaprogramwhileitwasexecuting.

Watchedanddynamicallychangedthevalueofprogramvariablesduringexecution.

Sawhowlocalvariablesareresettonilafterthefunctionthatdefinedthemcompletesitsrun.

ThetoolsyoulearnedinthislessonwillbepartofyourdailyworkifyouintendtodevelopAutoLISPapplicationswithVLISP.

Pleasesendusyourcommentaboutthispage

Page 48: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary

Inthislesson,youwillexpandyourprogramsoitactuallydrawssomethingwithinAutoCAD—thepolylineoutlineofthegardenpath.Todrawtheborder,youmustcreatesomeutilityfunctionsthatarenotspecifictoasingleapplicationbutaregeneralinnatureandmayberecycledforlateruse.Youwillalsolearnaboutwritingfunctionsthatacceptarguments—datathatispassedtothefunctionfromtheoutside—andwhytheuseofargumentsisapowerfulprogrammingconcept.Bytheendofthelesson,youwilldrawanAutoCADshapeparametrically,whichmeansdynamicallydrawingashapebasedontheuniquedataparametersprovidedbytheuser.

Topicsinthissection

PlanningReusableUtilityFunctionsDrawingAutoCADEntitiesEnablingtheBoundaryOutlineDrawingFunctionWrappingUpLesson3

Pleasesendusyourcommentaboutthispage

Page 49: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>

PlanningReusableUtilityFunctions

Utilityfunctionsperformtaskscommontomanyapplicationsyouwillbewriting.Thesefunctionsformatoolkityoucanuseoverandoveragain.

Whenyoucreateafunctionaspartofatoolkit,spendsometimedocumentingitthoroughly.Inyourcomments,alsonotethefeaturesyouwouldliketoaddtothefunctioninthefuture,shouldtimepermit.

Topicsinthissection

ConvertingDegreestoRadiansConverting3DPointsto2DPoints

Pleasesendusyourcommentaboutthispage

Page 50: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>PlanningReusableUtilityFunctions>

ConvertingDegreestoRadians

Youwillnowcreateafunctiontopreventyoufromrepetitivelytypinganequation.Itlookslikethis:

(defunDegrees->Radians(numberOfDegrees)

(*pi(/numberOfDegrees180.0)))

ThisfunctioniscalledDegrees->Radians.Thefunctionnameindicatesitspurpose.

Whydoyouneedafunctiontoconvertangularmeasurements?Behindthescenes,AutoCAD®usesradianangularmeasurementtokeeptrackofangles,whereasmostpeoplethinkintermsofdegrees.Thisfunctioninyourtoolkitallowsyoutothinkindegrees,andletsAutoLISP®convertthosenumberstoradians.

Totesttheutilityfunction

1. EnterthefollowingattheVLISPConsoleprompt:

(defunDegrees->Radians(numberOfDegrees)

(*pi(/numberOfDegrees180.0)))

2. EnterthefollowingattheVLISPConsoleprompt:

(degrees->radians180)

Thefunctionreturnsthenumber3.14159.Accordingtohowthisfunctionworks,180degreesisequivalentto3.14159radians.

Tousethisfunctionwithinyourprogram,simplycopythefunctiondefinitionfromtheConsolewindowintoyourgpmain.lspfile.Youcanpasteitanywhereinthefile,aslongasyoudonotpasteitintothemiddleofanexistingfunction.

Page 51: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Tocleanupyourwork,selectthetextyoujustpastedin,thenchoosetheFormatSelectionbutton;VLISPwillproperlyindentandformatthecode.

Next,addsomecommentsdescribingthefunction.Whenyouhavefullydocumentedthefunction,yourcodeshouldlooksomethinglikethis:

;;;--------------------------------------------------------------;

;;;Function:Degrees->Radians;

;;;--------------------------------------------------------------;

;;;Description:Thisfunctionconvertsanumberrepresentingan;

;;;angularmeasurementindegrees,intoitsradian;

;;;equivalent.Thereisnoerrorcheckingonthe;

;;;numberOfDegreesparameter--itisalways;

;;;expectedtobeavalidnumber.;

;;;--------------------------------------------------------------;

(defunDegrees->Radians(numberOfDegrees)

(*pi(/numberOfDegrees180.0))

)

Pleasesendusyourcommentaboutthispage

Page 52: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>PlanningReusableUtilityFunctions>

Converting3DPointsto2DPoints

Anotherusefulfunctioninthegardenpathprogramconverts3Dpointsto2Dpoints.AutoCADusuallyworkswith3Dcoordinates,butsomeentities,suchaslightweightpolylines,arealwaysmeanttobe2D.Thepointsreturnedbythegetpointfunctionare3D,soyouneedtocreateafunctiontoconvertthem.

Toconverta3Dpointtoa2Dpoint

1. EnterthefollowingattheConsolewindowprompt:

(defun3dPoint->2dPoint(3dpt)(list(car3dpt)(cadr3dpt)))

2. TestthefunctionbyenteringthefollowingattheConsoleprompt:

(3dpoint->2dpoint(list10200))

Thisworks,butthereisanotherconsiderationforthegardenpathapplication.Althoughitoftendoesn'tmatterwhetheranumberisanintegerorarealinLISPfunctions,thisisn'tthecasewithActiveXfunctions,whichyou'lluselaterinthislesson.ActiveXfunctionsrequirerealnumbers.Youcaneasilymodifythefunctiontoensureitreturnsrealsinsteadofintegers.

3. EnterthefollowingcodeattheConsoleprompt:

(defun3dPoint->2dPoint(3dpt)(list(float(car3dpt))

(float(cadr3dpt))))

4. Runthefunctionagain:

(3dpoint->2dpoint(list10200))

Noticethereturnvaluesarenowreals(indicatedbythedecimalvalues).

Page 53: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

5. Testthefunctionagain,thistimeusingthegetpointfunction.EnterthefollowingattheConsoleprompt:

(setqmyPoint(getpoint))

6. PickapointintheAutoCADdrawingarea.Thegetpointfunctionreturnsa3Dpoint.

7. EnterthefollowingattheConsoleprompt:

(3dPoint->2DpointmyPoint)

Notethe2Dpointreturned.Nowaddthefunctiontothegpmain.lspfile,justasyoudidwithDegrees->Radians.Thenewcodeshouldlooklikethefollowing:

;;;--------------------------------------------------------------;

;;;Function:3dPoint->2dPoint;

;;;--------------------------------------------------------------;

;;;Description:Thisfunctiontakesoneparameterrepresentinga;

;;;3Dpoint(listofthreeintegersorreals),and;

;;;convertsitintoa2Dpoint(listoftworeals).;

;;;Thereisnoerrorcheckingonthe3Dpoint;

;;;parameter--itisassumedtobeavalidpoint.;

;;;--------------------------------------------------------------;

;;;Todo:Addsomekindofparametercheckingsothatthis;

;;;functionwon'tcrashaprogramifitispasseda;

;;;nullvalue,orsomeotherkindofdatatypethana;

;;;3Dpoint.;

;;;--------------------------------------------------------------;

(defun3dPoint->2dPoint(3dpt)

(list(float(car3dpt))(float(cadr3dpt)))

)

Notethatthefunctionheadingincludesacommentaboutsomeworkyoushoulddoonthisfunctioninthefuture.Ifyouwanttoearnsomeextracredit,thinkabouthowyouwouldgoaboutfoolproofingthisfunctionsothatinvaliddatadoesnotmakeitcrash.Hint:numberpandlistpfunctions…

(listp'(110))=>T

(numberp3.4)=>T

Page 54: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Pleasesendusyourcommentaboutthispage

Page 55: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>

DrawingAutoCADEntities

MostAutoLISPprogramsdrawentitiesusingoneofseveralmethods:

ActiveXfunctions

Theentmakefunction

Thecommandfunction

ThislessonfocusesonentitycreationbyActiveX®.InLesson5,youwillimplementtheentmakeandAutoCADcommandalternatives.

Topicsinthissection

CreatingEntitiesUsingActiveXFunctionsUsingentmaketoBuildEntitiesUsingtheAutoCADCommandLine

Pleasesendusyourcommentaboutthispage

Page 56: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>DrawingAutoCADEntities>

CreatingEntitiesUsingActiveXFunctions

ThenewestwayofcreatingentitiesisbyusingtheActiveXfunctionswithinVLISP.ActiveXhasseveraladvantagesoverentmakeandcommand.

ActiveXfunctionsarefaster.

ActiveXfunctionnamesindicatetheactiontheyperform,resultingineasierreadability,maintenance,andbug-fixing.

YouwillseeanexampleofanActiveXfunctionlaterinthislesson.

Pleasesendusyourcommentaboutthispage

Page 57: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>DrawingAutoCADEntities>

UsingentmaketoBuildEntities

Theentmakefunctionallowsyoutobuildanentitybygatheringvaluesforthingssuchascoordinatelocationandorientation,layer,andcolorintoanassociationlist,thenaskingAutoCADtobuildtheentityforyou.Theassociationlistyoubuildfortheentmakefunctionlooksverymuchliketheassociationlistyougetbackwhenyoucalltheentgetfunction.Thedifferenceisthatentgetreturnsinformationaboutanentity,whileentmakebuildsanewentityfromrawdata.

Pleasesendusyourcommentaboutthispage

Page 58: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>DrawingAutoCADEntities>

UsingtheAutoCADCommandLine

WhenAutoLISPfirstappearedinAutoCAD,theonlyavailablemeansforentitycreationwasthecommandfunction.ThisallowsanAutoLISPprogrammertocodejustaboutanycommandthatcanbeexecutedfromtheAutoCADCommandprompt.Thisisreliable,butitisnotasfastasActiveXmethodsanddoesnotprovidetheflexibilityofentmake.

Pleasesendusyourcommentaboutthispage

Page 59: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>

EnablingtheBoundaryOutlineDrawingFunction

Afterthelastlesson,thegp:drawOutlinefunctionlookedlikethefollowing:

;;;--------------------------------------------------------------;

;;;Function:gp:drawOutline;

;;;--------------------------------------------------------------;

;;;Description:Thisfunctiondrawstheoutlineofthe;

;;;gardenpath.;

;;;--------------------------------------------------------------;

(defungp:drawOutline()

(alert

(strcat"Thisfunctionwilldrawtheoutlineofthepolyline"

"\nandreturnapolylineentityname/pointer."

)

)

;;Fornow,simplyreturnaquotedsymbol.Eventually,this

;;functionwillreturnanentitynameorpointer.

'SomeEname

)

Asitexists,thecodedoesnotdomuch.However,usingtheassociationlistinformationstoredinthevariablegp_PathData,youhaveenoughinformationtocalculatethepointsforthepathboundary.Younowhavetodeterminehowtopasstheinformationinthatvariabletogp:drawOutline.

Remembergp_PathDataisalocalvariabledefinedwithintheC:GPathfunction.InAutoLISP,localvariablesdeclaredinonefunctionarevisibletoanyfunctioncalledfromthatfunction(refertoDifferentiatingBetweenLocalandGlobalVariablesforclarification).Thegp:drawOutlinefunctioniscalledfromwithinC:GPath.Youcanrefertothegp_PathDatavariableingp:drawOutline,butthisisnotagoodprogrammingpractice.

Why?Whenthetwofunctionsusingthesamevariablearedefinedinthesamefile,asintheexamplesshownsofar,itisnottoodifficulttofigureoutwherethe

Page 60: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

variableisdefinedandwhatitisusedfor.Butifthefunctionsaredefinedindifferentfiles—asisoftenthecase—youwouldhavetosearchthroughbothfilestofigureoutwhatgp_PathDatarepresents.

Topicsinthissection

PassingParameterstoFunctionsWorkingwithanAssociationListUsingAnglesandSettingUpPointsUnderstandingtheActiveXCodeingp:drawOutlineEnsuringThatActiveXIsLoadedObtainingaPointertoModelSpaceConstructinganArrayofPolylinePointsConstructingaVariantfromaListofPointsPuttingItAllTogether

Pleasesendusyourcommentaboutthispage

Page 61: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>EnablingtheBoundaryOutlineDrawingFunction>

PassingParameterstoFunctions

Abetterwaytoconveyinformationfromonefunctiontoanotheristopassparameterstothecalledfunction.Designthefunctionsoitexpectstoreceiveanumberofvalues.RemembertheDegrees->Radiansfunction?ThisfunctionispassedaparameternamednumberOfDegrees:

(defunDegrees->Radians(numberOfDegrees)

(*pi(/numberOfDegrees180.0)))

Whenyoucallthefunction,itexpectsyoutopassitanumber.ThenumberwithinDegrees->RadiansisdeclaredastheparameternamednumberOfDegrees.Forexample:

_$(degrees->radians90)1.5708

Inthiscase,thenumber90isassignedtotheparameternumberOfDegrees.

Youcanalsopassavariabletoafunction.Forexample,youmighthaveavariablecalledaDegreeValuethatcontainsthenumber90.ThefollowingcommandssetaDegreeValueandpassthevariabletoDegrees->Radians:

_$(setqaDegreeValue90)90

_$(degrees->radiansaDegreeValue)1.5708

Pleasesendusyourcommentaboutthispage

Page 62: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>EnablingtheBoundaryOutlineDrawingFunction>

WorkingwithanAssociationList

Youcanpasstheassociationlistinthegp_PathDatavariabletothegp:drawOutlinefunctionbyinvokingthefunctionasfollows:

(gp:drawOutlinegp_PathData)

Simpleenough,butyoualsoneedtofigureouthowtoprocesstheinformationstoredintheassociationlist.TheVLISPInspectfeaturecanhelpyoudeterminewhattodo.

TousetheVLISPInspectfeaturetoanalyzeyourassociationlist

1. Loadthecodethatisinthetexteditorwindow.

2. EnterthefollowingexpressionattheConsoleprompt:

(setqBoundaryData(gp:getPointInput))

VLISPwillstoretheinformationyouprovideinavariablenamedBoundaryData.

3. Respondtothepromptsforstartpoint,endpoint,andhalf-width.

4. SelecttheBoundaryDatavariablenameintheConsolewindowbydouble-clickingit.

5. ChooseView InspectfromtheVLISPmenu.

VLISPdisplaysawindowlikethefollowing:

Page 63: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

TheInspectwindowshowsyoueachsublistwithintheBoundaryDatavariable.

6. EnterthefollowingattheVLISPConsoleprompt:

(assoc50BoundaryData)

Theassocfunctionreturnstheentryintheassociationlistthatisidentifiedbythespecifiedkey.Inthisexample,thespecifiedkeyis50;thisisassociatedwiththeangleofthegardenpath(seePuttingAssociationListstoUseforalistofthekey-valuepairsdefinedforthisapplication).

7. EnterthefollowingattheVLISPConsoleprompt:

(cdr(assoc50BoundaryData))

Thecdrfunctionreturnsthesecondelement,andanyremainingelementsafterthat,fromalist.Inthisexample,cdrretrievestheanglevalue,whichisthesecondandlastelementintheentryreturnedbytheassocfunction.Bythispoint,youshouldhavenotroubleunderstandingthefollowingcodefragment:

(setqPathAngle(cdr(assoc50BoundaryData))

Width(cdr(assoc40BoundaryData))

HalfWidth(/Width2.00)

StartPt(cdr(assoc10BoundaryData))

PathLength(cdr(assoc41BoundaryData))

Pleasesendusyourcommentaboutthispage

Page 64: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>EnablingtheBoundaryOutlineDrawingFunction>

UsingAnglesandSettingUpPoints

Therearestillacoupleofissuesremaining.First,youneedtofigureouthowtodrawthepathatanyangletheuserspecifies.Fromthegp:getPointInputfunction,youcaneasilyestablishtheprimaryangleofthepath.Todrawit,youneedacoupleofadditionalvectorsperpendiculartotheprimaryangle.

ThisiswheretheDegrees->Radiansfunctionisuseful.ThefollowingcodefragmentdemonstrateshowyoucansetupyourtwoperpendicularvectorsusingthePathAnglevariableasanargumentpassedtotheDegrees->Radiansfunction:

(setqangp90(+PathAngle(Degrees->Radians90))

angm90(-PathAngle(Degrees->Radians90)))

Withthedatayounowhaveinhand,youcanestablishthefourcornerpointsofthepathusingpolarfunction:

Page 65: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(setqp1(polarStartPtangm90HalfWidth)

p2(polarp1PathAnglePathLength)

p3(polarp2angp90Width)

p4(polarp3(+PathAngle(Degrees->Radians180))

Thepolarfunctionreturnsa3Dpointataspecifiedangleanddistancefromapoint.Forinstance,polarlocatesp2byprojectingp1adistanceofPathLengthalongavectororientedatanangleofPathAngle,counter-clockwisefromthex-axis.

Pleasesendusyourcommentaboutthispage

Page 66: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>EnablingtheBoundaryOutlineDrawingFunction>

UnderstandingtheActiveXCodeingp:drawOutline

Thegp:drawOutlinefunctionissuesActiveXcallstodisplaythepath'spolylineborderinAutoCAD.ThefollowingcodefragmentusesActiveXtodrawtheborder:

;;AddpolylinetothemodelspaceusingActiveXautomation.

(setqpline(vla-addLightweightPolyline

*ModelSpace* ;GlobalDefinitionforModelSpace

VLADataPts ;verticesofpathboundary

);_endofvla-addLightweightPolyline

);_endofsetq

(vla-put-closedplineT)

Howdoyoumakesenseofthiscode?AnessentialresourceistheActiveXandVBAReference,whichdescribesthemethodsandpropertiesaccessibletoActiveXclientssuchasthisgardenpathapplication.The“WorkingwithActiveX”sectionoftheAutoLISPDeveloper'sGuideexplainshowtotranslatetheVBA™syntaxintheActiveXandVBAReferenceintoActiveXcallsinAutoLISPsyntax.

Forthemoment,though,youcangainarudimentaryunderstandingbyscrutinizingthepatternofthetwovla-callsintheprecedingexample.ThenamesofallAutoLISPActiveXfunctionsthatworkonAutoCADobjectsareprefixedwithvla-.Forexample,addLightweightPolylineisthenameofanActiveXmethod,andvla-addLightweightPolylineistheAutoLISPfunctionthatinvokesthismethod.Thevla-put-closedcallupdatestheclosedpropertyoftheplineobject,thepolylinedrawnbyvla-addLightweightPolyline.

TheAutomationobjectsthatfactorintoAutoLISPActiveXcallsabidebyafewstandardrules:

Thefirstargumenttoavla-put,vla-get,orvla-methodcallistheobjectbeingmodifiedorqueried,forexample,*ModelSpace*in

Page 67: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

thefirstfunctioncallandplineinthesecondcall.

Thereturnvalueofavla-methodcallisaVLA-object,whichcanbeusedinsubsequentcalls.Forexample,vla-addLightweightPolylineyieldsareturnobject,pline,thatisalteredinthenextActiveXcall.

TheActiveXobjectmodelisstructuredhierarchically.Objectsaretraversedfromtheapplicationobjectatthetopmostleveldowntoindividualdrawingprimitives,suchaspolylineandcircleobjects.Thus,thegp:drawOutlinefunctionisnotyetcomplete,becausethe*ModelSpace*automationobjectmustfirstbeaccessedthroughtherootapplicationobject.

Pleasesendusyourcommentaboutthispage

Page 68: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>EnablingtheBoundaryOutlineDrawingFunction>

EnsuringThatActiveXIsLoaded

ActiveXfunctionalityisnotautomaticallyenabledwhenyoustartAutoCADorVLISP,soyourprogramsmustensurethatActiveXisloaded.Thefollowingfunctioncallaccomplishesthis:

(vl-load-com)

IfActiveXsupportisnotyetavailable,executingvl-load-cominitializestheAutoLISPActiveXenvironment.IfActiveXisalreadyloaded,vl-load-comdoesnothing.

Pleasesendusyourcommentaboutthispage

Page 69: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>EnablingtheBoundaryOutlineDrawingFunction>

ObtainingaPointertoModelSpace

WhenyouaddentitiesthroughActiveXfunctions,youneedtoidentifythemodelspaceorpaperspaceinwhichtheentityistobeinserted.(InActiveXterminology,entitiesareobjects,butthistutorialwillcontinueusingthetermentity.)TotellAutoCADwhichspacethenewentitiesshouldoccupy,youneedtoobtainapointertothatspace.Unfortunately,obtainingapointertomodelspaceisnotasimple,single-shotfunction.Thefollowingcodefragmentshowshowtheoperationneedstobesetup:

(vla-get-ModelSpace(vla-get-ActiveDocument

(vlax-get-Acad-Object)))

Workingfromtheinsideout,thevlax-get-Acad-ObjectfunctionretrievesapointertoAutoCAD.Thispointerispassedtothevla-get-ActiveDocumentfunction,whichretrievesapointertotheactivedrawing(document)withinAutoCAD.TheActiveDocumentpointeristhenpassedtothevla-get-ModelSpacefunctionthatretrievesapointertothemodelspaceofthecurrentdrawing.

Thisisnotthekindofexpressionyouwanttotypeoverandover.Forexample,lookathowmuchmorecomplicatedthecodeforaddingapolylineusingActiveXappearswhentheentiremodelspaceexpressionisused:

(setqpline(vla-addLightweightPolyline

(vla-get-ModelSpace

(vla-get-ActiveDocument

(vlax-get-Acad-Object)

)

)

VLADataPts)

)

(vla-put-closedplineT)

Thefunctionisdefinitelylessunderstandable.Notonlythat,butwithinevery

Page 70: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

expressionwithinyourprogramwhereanentityiscreated,yourepeatthesamesetofnestedfunctions.Thisdemonstratesoneofthefewexcellentusesforglobalvariables.Thegardenpathapplicationcanaddalotofentitiestomodelspace(thinkofallthetilesinthepath),so,setupaglobalvariabletostorethepointertothemodelspace,asinthefollowingcode:

(setq*ModelSpace*(vla-get-ModelSpace(vla-get-ActiveDocument

(vlax-get-Acad-Object))))

Youcanusethevariable*ModelSpace*anytimeyoucallanActiveXentitycreationfunction.Theonlytrickythingwiththisschemeisthe*ModelSpace*variablemustbereadytogobeforeyoustartdrawing.Forthisreason,thesetqestablishingthisvariablewillbecalledatthetimetheapplicationisloaded,immediatelyafterthecalltovl-load-com.Thesecallswillbeplacedbeforeanydefunintheprogramfile.Asaresult,theyareexecutedassoonasthefileisloaded.

Pleasesendusyourcommentaboutthispage

Page 71: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>EnablingtheBoundaryOutlineDrawingFunction>

ConstructinganArrayofPolylinePoints

Thelastissuetodealwithishowtotransformtheindividualpointvariables—p1,p2,p3,andp4—intotheformatrequiredforthevla-addLightweightpolylinefunction.First,getsomehelponthetopic.

Toobtaininformationonafunction

1. ChoosetheHelpbuttonontheVLISPtoolbar.

2. Entervla-addLightweightpolylineintheEnterItemNamedialogbox,andchooseOK.(TheHelpsystemisnotcasesensitive,sodonotworryabouthowyoucapitalizethefunctionname.)

HelpstatesthatAddLightWeightPolylinerequiresyoutospecifythepolylineverticesasanarrayofdoublesintheformofavariant.HereishowHelpdescribesthisparameter:

Thearrayof2DWCScoordinatesspecifyingtheverticesofthepolyline.Atleasttwopoints(fourelements)arerequiredforconstructingalightweightpolyline.Thearraysizemustbeamultipleof2.

AvariantisanActiveXconstructthatservesasacontainerforvarioustypesofdata.Strings,integers,andarrayscanallberepresentedbyvariants.Thevariantstoresdataalongwiththeinformationidentifyingthedata.

Sofar,youhavefourpoints,eachintheformat(x,y,z).Thechallengeistoconvertthesefourpointsintoalistofthefollowingform:

(x1y1x2y2x3y3x4y4)

Theappendfunctiontakesmultiplelistsandconcatenatesthem.TocreatealistofthefourpointsintheproperformatfortheActiveXfunction,youcanusethefollowingexpression:

Page 72: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(setqpolypoints(append(3dPoint->2dPointp1)

(3dPoint->2dPointp2)

(3dPoint->2dPointp3)

(3dPoint->2dPointp4)))

Writingthe3dPoint->2dPointfunctionfourtimesisabitcumbersome.Youcanreducethecodefurtherbyusingthemapcarandapplyfunctions.Whenselected,mapcarexecutesafunctiononindividualelementsinoneormorelists,andapplypassesalistofargumentstothespecifiedfunction.Theresultingcodelookslikethefollowing:

(setqpolypoints(apply'append(mapcar'3dPoint->2dPoint

(listp1p2p3p4))))

Beforethecalltomapcar,thelistofpointsisinthisform:

((x1y1z1)(x2y2z2)(x3y3z3)(x4y4z4))

Aftermapcaryouhavealistofpointsinthefollowingform:

((x1y1)(x2y2)(x3y3)(x4y4))

Andfinally,afterapplyingtheappendfunctiononthelistreturnedfrommapcar,youendupwiththefollowing:

(x1y1x2y2x3y3x4y4)

Pleasesendusyourcommentaboutthispage

Page 73: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>EnablingtheBoundaryOutlineDrawingFunction>

ConstructingaVariantfromaListofPoints

Sofar,thedatainthepolypointsvariableisinalistformatsuitableformanyAutoLISPcalls.However,thedataistobesuppliedasaninputparametertoanActiveXcallthatexpectsavariantarrayofdoubles.Youcanuseanotherutilityfunctiontomaketherequiredconversionfromlisttovariant:

(defungp:list->variantArray(ptsList/arraySpacesArray)

;allocatespaceforanarrayof2dpointsstoredasdoubles

(setqarraySpace(vlax-make-safearray

vlax-vbdouble;elementtype

(cons0

(-(lengthptsList)1)

);arraydimension

)

)

(setqsArray(vlax-safearray-fillarraySpaceptsList))

;returnarrayvariant

(vlax-make-variantsArray)

)

Thefollowingactionstakeplaceingp:list->variantArray:

Thevlax-make-safearrayfunctioniscalledtoallocateanarrayofdoubles(vlax-vbdouble).Thevlax-make-safearrayfunctionalsorequiresyoutospecifythelowerandupperindexboundariesofthearray.Ingp:list->variantArray,thecalltovlax-make-safearrayspecifiesastartindexof0andsetstheupperlimittoonelessthanthenumberofelementspassedtoit(ptsList).

Thevlax-safearray-fillfunctioniscalledtopopulatethearraywiththeelementsinthepointlist.

Thevlax-make-variantiscalledtoconvertthesafearrayintoavariant.Asthelastfunctioncallingp:list->variantArray,the

Page 74: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

returnvalueispassedtothecallingfunction.

Thefollowingisanexampleofafunctioncallthatinvokesgp:list->variantArraytoconvertalisttoavariantarrayofdoubles:

;dataconversionfromlisttovariant

(setqVLADataPts(gp:list->variantArraypolypoints))

Pleasesendusyourcommentaboutthispage

Page 75: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>EnablingtheBoundaryOutlineDrawingFunction>

PuttingItAllTogether

Younowhaveallthecodeyouneedtodrawtheoutlineofthegardenpath.

Toupdateyourcode

1. Replaceyouroldcodeforthegp:drawOutlinefunctionwiththefollowing:

;;;---------------------------------------------------------------

;;;Function:gp:drawOutline

;;;---------------------------------------------------------------

;;;Description:Thisfunctionwilldrawtheoutlineofthegarden

;;;path.

;;;---------------------------------------------------------------

;;;Note:Noerrorcheckingorvalidationisperformedonthe

;;;BoundaryDataparameter.Thesequenceofitemswithinthis

;;;parameterdoesnotmatter,butitisassumedthatallsublists

;;;arepresentandcontainvaliddata.

;;;--------------------------------------------------------------

(defungp:drawOutline(BoundaryData/VLADataPtsPathAngle

WidthHalfWidthStartPtPathLength

angm90angp90p1p2

p3p4polypointspline

)

;;extractthevaluesfromthelistBoundaryData

(setqPathAngle(cdr(assoc50BoundaryData))

Width(cdr(assoc40BoundaryData))

HalfWidth(/Width2.00)

StartPt(cdr(assoc10BoundaryData))

PathLength(cdr(assoc41BoundaryData))

angp90(+PathAngle(Degrees->Radians90))

angm90(-PathAngle(Degrees->Radians90))

p1(polarStartPtangm90HalfWidth)

p2(polarp1PathAnglePathLength)

p3(polarp2angp90Width)

p4(polarp3(+PathAngle(Degrees->Radians180))PathLength)

polypoints(apply'append

Page 76: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(mapcar'3dPoint->2dPoint(listp1p2p3p4))

)

)

;;*****dataconversion*****

;;Notice,polypointsisinAutoLISPformat,consistingofalist

;;ofthe4cornerpointsforthegardenpath.

;;Thevariableneedstobeconvertedtoaformofinputparameter

;;acceptabletoActiveXcalls.

(setqVLADataPts(gp:list->variantArraypolypoints))

;;AddpolylinetothemodelspaceusingActiveXautomation.

(setq pline(vla-addLightweightPolyline

*ModelSpace*;GlobalDefinitionforModelSpace

VLADataPts

);_endofvla-addLightweightPolyline

);_endofsetq

(vla-put-closedplineT)

;;ReturntheActiveXobjectnamefortheoutlinepolyline

;;Thereturnvalueshouldlooksomethinglikethis:

;;#<VLA-OBJECTIAcadLWPolyline02351a34>

pline

);_endofdefun

Notethatgp:drawOutlinenowreturnsthevariablepline,notthequotedsymbol'SomeEnameusedinthestubbed-outversionofthefunction.

2. FormatthecodeyoujustenteredbyselectingitandchoosingtheFormatSelectionbuttonontheVLISPtoolbar.

3. EnableActiveXandaddtheglobalvariableassignmentforthepointertomodelspace,asdescribedearlier.Scrolltothetopofthetexteditorwindowandaddthefollowingcodebeforethefirstdefun:

;;;--------------------------------------------------------------

;;;FirststepistoloadActiveXfunctionality.IfActiveXsupport

;;;alreadyexistsindocument(canoccurwhenBonustoolshavebeen

;;;loadedintoAutoCAD),nothinghappens.Otherwise,ActiveX

;;;supportisloaded.

;;;---------------------------------------------------------------

(vl-load-com)

;;;InLesson4,thefollowingcommentandcodeismovedtoutils.lsp

;;;---------------------------------------------------------------

;;;ForActiveXfunctions,weneedtodefineaglobalvariablethat

;;;"points"totheModelSpaceportionoftheactivedrawing.This

;;;variable,named*ModelSpace*willbecreatedatloadtime.

;;;---------------------------------------------------------------

(setq*ModelSpace*

(vla-get-ModelSpace

Page 77: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(vla-get-ActiveDocument(vlax-get-acad-object))

);_endofvla-get-ModelSpace

);_endofsetq

Notehowtheabovecodelivesoutsideofanydefun.Becauseofthis,VLISPautomaticallyexecutesthecodeatthetimeyouloadthefile.

4. LookforthefollowinglineintheC:GPathfunction:

(setqPolylineName(gp:drawOutline))

Changeittothefollowing:

(setqPolylineName(gp:drawOutlinegp_PathData))

Thegp:drawOutlinefunctionisnowexpectingaparameter—thelistcontainingthepolylineboundarydata—andthischangefulfillsthatrequirement.

5. Addthegp:list->variantArrayfunctionshowninConstructingaVariantfromaListofPointstotheendofgpmain.lsp.Tryloadingandrunningtherevisedprogram.VLISPtakescontrolawayfromAutoCADbeforeyouseetheendresult,soswitchbacktotheAutoCADwindowaftercontrolreturnstoVLISP.Iftheprogramrancorrectly,youshouldseeaborderforthegardenpath.Ifyoufinderrors,debugthecodeandtryagain.

Pleasesendusyourcommentaboutthispage

Page 78: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingthePathBoundary>

WrappingUpLesson3

Inthislesson,you

Wroteutilityfunctionsthatcanbereusedinotherapplications.

Addedentitycreationlogictoyourprogram.

LearnedhowtouseActiveXfunctions.

Learnedhowtoworkwithassociationlists.

Enabledyourprogramtodrawagardenpathborder.

Ifyou'reconfusedaboutanythingfromthislesson,itisrecommendedyougothroughitonceagainbeforemovingontoLesson4.(Ifyoudecidetodoso,copythecompletedcodefromyourLesson2directorysothatyoustartthelessonfromthecorrectplace.)Andifallelsefails,youcanalwayscopythecodefromtheTutorial\VisualLISP\Lesson3directory.

Pleasesendusyourcommentaboutthispage

Page 79: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface

Inthislesson,youwillaccomplishtwomajortasks:creatingaVisualLISP®projectandaddingadialog-basedinterfacetoyourapplication.Intheprocess,youwillsplitthesingleAutoLISP®fileyouworkedwithsofar(gpmain.lsp)intoseveralsmallerfiles,reinforcingtheconceptofcodemodularity.

Fromthislessonon,thetutorialprovidesmoregeneraldescriptionsofthetasksyouneedtoperform,unlessnewtopicsarecovered.Also,thecodefragmentswillbeminimallydocumentedtosavespace.

Topicsinthissection

ModularizingYourCodeUsingVisualLISPProjectsAddingtheDialogBoxInterfaceInteractingwiththeDialogBoxfromAutoLISPCodeProvidingaChoiceofBoundaryLineTypeCleaningUpRunningtheApplicationWrappingUpLesson4

Pleasesendusyourcommentaboutthispage

Page 80: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>

ModularizingYourCode

AsaresultoftheworkyoudidinLesson3,yourgpmain.lspfilewasgettingratherlarge.ThisisnotaproblemforVLISP,butitiseasiertomaintainthecodeifyousplitthingsupintofilescontaininglogicallyrelatedfunctions.It'salsoeasiertodebugyourcode.Forexample,ifyouhaveasinglefilewith150functions,asinglemissingparenthesiscanbedifficulttofind.

Inthetutorial,thefileswillbeorganizedasfollows:

Tutorialfileorganization

Filename Contents

gp-io.lsp Allinputandoutput(I/O)functions)suchasgettinguserinput.AlsocontainstheAutoLISPcoderequiredforthedialogboxinterfaceyouwillbeadding.

utils.lsp Includesallgenericfunctionsthatcanbeusedagainonotherprojects.Alsocontainsload-timeinitializations.

gpdraw.lsp Alldrawingroutines—thecodethatactuallycreatestheAutoCADentities.

gpmain.lsp ThebasicC:GPathfunction.

Page 81: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Tosplitgpmain.lspintofourfiles

1. Createanewfile,thencutandpastethefollowingfunctionsfromgpmain.lspintothenewfile:

gp:getPointInput

gp:getDialogInput

Savethenewfileinyourworkingdirectoryasgp-io.lsp.

2. Createanewfile,thencutandpastethefollowingfunctionsfromgpmain.lspintothenewfile:

Degrees->Radians

3Dpoint->2Dpoint

gp:list->variantArray

Also,atthebeginningofthefile,insertthelinesofcodetoestablishActiveXfunctionality(vl-load-com)andcommitglobalvariableassignment(*ModelSpace*).Savethefileasutils.lsp.

3. Createanewfile,thencutandpastethefollowingfunctionfromgpmain.lspintothenewfile:

gp:drawOutline

Savethisfileasgpdraw.lsp.

4. Afterstrippingthecodeoutofgpmain.lsp,saveitandcheckit.Onlytheoriginalfunction,C:GPath,shouldremaininthefile.

YourVLISPdesktopisstartingtogetcrowded.YoucanminimizeanywindowwithinVLISPanditstaysaccessible.ChoosetheSelectWindowbuttononthetoolbartochooseawindowfromalist,orchooseWindowfromtheVLISPmenuandselectawindowtoview.

Pleasesendusyourcommentaboutthispage

Page 82: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>

UsingVisualLISPProjects

TheVLISPprojectfeatureprovidesaconvenientwaytomanagethefilesthatmakeupyourapplication.Andwiththeprojectfeature,youcanopenasingleprojectfileinsteadofindividuallyopeningeveryLISPfileintheapplication.Oncetheprojectisopen,gettingtoitsconstituentfilesisadouble-clickaway.

TocreateaVLISPproject

1. ChooseProject NewProjectfromtheVLISPmenu.

2. SavethefileinyourLesson4directory,usingthenamegpath.prj.Afteryousavethefile,VLISPdisplaystheProjectPropertiesdialogbox.

3. Choosethe[Un]SelectAllbuttonontheleftintheProjectPropertiesdialogbox.

4. Choosethebuttoncontaininganarrowpointingtotheright.Thisaddsalltheselectedfilestoyourproject.

IntheProjectPropertiesdialogbox,thelistboxontheleftshowsallLISPfilesthatresideinthesamedirectoryasyourprojectfileandarenotincludedinthatproject.Thelistboxontherightlistsallthefilesthatmakeuptheproject.Whenyouaddtheselectedfilestotheproject,thosefilenamesmovefromtheleftboxtotherightbox.

5. Inthelistboxontherightsideofthedialogbox,selectgpmain,thenchoosetheBottombutton.Thismovesthefiletothebottomofthelist.VLISPloadsprojectfilesintheordertheyarelisted.Becausethepromptthattellsusersthenameofthecommandislocatedattheendofthegpmain.lspfile,youneedtomovethisfiletothebottomofthelist.

Page 83: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Loadingthisfilelastresultsinthepromptdisplayedtousers.Theutils.lspfileshouldbeloadedfirstbecauseitcontainsinitializationcodefortheapplication.Therefore,selectutilsinthedialog'slistboxandchoosetheTopbutton.

6. ChooseOK.

VLISPaddsasmallprojectwindowtoyourVLISPdesktop.Thewindowliststhefilesinyourproject.Double-clickonanyfiletoopenthefileintheVLISPtexteditor(ifitisnotalreadyopen)andmakeittheactiveeditorwindow.

Pleasesendusyourcommentaboutthispage

Page 84: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>

AddingtheDialogBoxInterface

Thenextpartofthislessonconcernsaddingadialogboxinterfacetothegardenpathapplication.Todothis,youwillbeworkingwithanotherlanguage,dialogcontrollanguage(DCL).

Currently,yourgpathfunctiononlyacceptsinputonthecommandline.Youincludedastubbed-outfunction(gp:getDialogInput)withtheintentionofaddingadialogboxinterface.Nowisthetimetoaddtheinterface.

Therearetwostepsincreatingafunctionaldialoginterface:

Definetheappearanceandcontentsofthedialogboxes.

Addprogramcodetocontroldialogbehavior.

Thedescriptionandformatofadialogboxisdefinedina.dclfile.IntheAutoLISPDeveloper'sGuide,DCLisdescribedinchapter11,“DesigningDialogBoxes”chapter12,“ManagingDialogBoxes”,andchapter13,“ProgrammableDialogBoxReference”.

Programcodethatinitializesdefaultsettingsandrespondstouserinteractionwillbeaddedtogp:getDialogInput.

Topicsinthissection

DefiningtheDialogBoxwithDCLSavingaDCLFilePreviewingaDialogBox

Pleasesendusyourcommentaboutthispage

Page 85: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>AddingtheDialogBoxInterface>

DefiningtheDialogBoxwithDCL

Beginbytakingalookatthedialogboxyouneedtocreate.

Thedialogboxcontainsthefollowingelements:

Twosetsofradiobuttons.Onesetofbuttonsdeterminesthepolylinestyleoftheboundary,andtheothersetofbuttonsspecifiesthetileentitycreationmethod(ActiveX,entmake,orcommand).Onlyoneradiobuttoninasetcanbeselectedatonetime.

Editboxesforspecifyingtheradiusoftilesandthespacingbetweentiles.

AstandardsetofOKandCancelbuttons.

DialogboxcomponentsarereferredtoastilesinDCL.WritingthecompletecontentsofadialogboxDCLfilemayseemoverwhelming.Thetrickistosketchoutwhatyouwant,breakitdownintosections,thenwriteeachsection.

Page 86: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Todefinethedialogbox

1. OpenanewfileintheVLISPtexteditorwindow.

2. Enterthefollowingstatementinthenewfile:

label="GardenPathTileSpecifications";

ThisDCLstatementdefinesthetitleofthedialogboxwindow.

3. Definetheradiobuttonsforspecifyingpolylinetypebyaddingthefollowingcode:

:boxed_radio_column{//definestheradiobuttonareas

label="OutlinePolylineType";

:radio_button{//definesthelightweightradiobutton

label="&Lightweight";

key="gp_lw";

value="1";

}

:radio_button{//definestheold-stylepolylineradiobutton

label="&Old-style";

key="gp_hw";

}

}

Theboxed_radio_columnDCLdirectivedefinesaboxboundaryandallowsyoutospecifyalabelforthesetofbuttons.Withintheboundary,youspecifytheradiobuttonsyouneedbyaddingradio_buttondirectives.Eachradiobuttonrequiresalabelandakey.ThekeyisthenamebywhichyourAutoLISPcodecanrefertothebutton.Noticethattheradiobuttonlabeled“lightweight”isgivenavalueof1.Avalueof1(astring,notaninteger)assignedtoabuttonmakesitthedefaultchoiceinarowofbuttons.Inotherwords,whenyoufirstdisplaythedialog,thisbuttonwillbeselected.AlsonoticethatinDCLfiles,double-slashcharacters,notsemicolonsasinAutoLISP,indicateacomment.

4. Definetheradiocolumnfortheselectionoftheentitycreationstylebyaddingthefollowingcode:

:boxed_radio_column{//definestheradiobuttonareas

label="TileCreationMethod";

Page 87: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

:radio_button{//definestheActiveXradiobutton

label="&ActiveXAutomation";

key="gp_actx";

value="1";

}

:radio_button{//definesthe(entmake)radiobutton

label="&Entmake";

key="gp_emake";

}

:radio_button{//definesthe(command)radiobutton

label="&Command";

key="gp_cmd";

}

}

5. Addthefollowingcodetodefinetheeditboxtilesthatallowuserstoenterthenumbersspecifyingtilesizeandspacing:

:edit_box{//definestheRadiusofTileeditbox

label="&Radiusoftile";

key="gp_trad";

edit_width=6;

}

:edit_box{//definestheSpacingBetweenTileseditbox

label="S&pacingbetweentiles";

key="gp_spac";

edit_width=6;

}

Noticethatthisdefinitiondoesnotsetanyinitialvaluesfortheeditboxes.YouwillsetdefaultvaluesforeacheditboxinyourAutoLISPprogram.

6. AddthefollowingcodefortheOKandCancelbuttons:

:row{//definestheOK/Cancelbuttonrow

:spacer{width=1;}

:button{//definestheOKbutton

label="OK";

is_default=true;

key="accept";

width=8;

fixed_width=true;

}

:button{//definestheCancelbutton

label="Cancel";

is_cancel=true;

key="cancel";

Page 88: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

width=8;

fixed_width=true;

}

:spacer{width=1;}

}

Bothbuttonsaredefinedwithinarow,sotheylineuphorizontally.

7. ScrolltothebeginningofthetexteditorwindowandinsertthefollowingstatementasthefirstlineinyourDCL:

gp_mainDialog:dialog{

8. Thedialogdirectiverequiresaclosingbrace,soscrolltotheendofthefileandaddthebraceasthelastlineofDCLcode:

}

Pleasesendusyourcommentaboutthispage

Page 89: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>AddingtheDialogBoxInterface>

SavingaDCLFile

BeforesavingthefilecontainingyourDCL,considerthefactthatAutoCAD®

mustbeabletolocateyourDCLfileduringruntime.Forthisreason,thefilemustbeplacedinoneoftheAutoCADSupportFileSearchPathlocations.(Ifyouareunsureabouttheselocations,chooseTools OptionsfromtheAutoCADmenuandexaminetheSupportFileSearchPathlocationsundertheFilestab.)

Fornow,youcansavethefileintheAutoCADSupportdirectory.

TosaveyourDCLfile

1. ChooseFile SaveAsfromtheVLISPmenu.

2. IntheSaveAsTypefieldoftheSaveAsdialogbox,chooseDCLSourceFilesfromthepull-downmenu.

3. ChangetheSaveInpathto<AutoCADdirectory>\Support.

4. Enterthefilenamegpdialog.dcl.

5. ChooseSave.

NoticeVLISPchangesthesyntaxcoloringschemeafteryousavethefile.VLISPisdesignedtorecognizeDCLfilesandhighlightthedifferenttypesofsyntacticalelements.

Pleasesendusyourcommentaboutthispage

Page 90: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>AddingtheDialogBoxInterface>

PreviewingaDialogBox

VLISPprovidesapreviewfeatureforcheckingtheresultsofyourDCLcoding.

TopreviewadialogboxdefinedwithDCL

1. ChooseTools InterfaceTools PreviewDCLinEditorfromtheVLISPmenu.

2. ChooseOKwhenpromptedtospecifyadialogname.Inthiscase,yourDCLfiledefinesjustasingledialogbox,sothereisnochoicetobemade.Asyoucreatelargerandmorerobustapplications,however,youmayendupwithDCLfilescontainingmultipledialogboxes.Thisiswhereyoucanselectwhichonetopreview.

3. Ifthedialogboxdisplayssuccessfully,chooseanybuttontoendthedialog.

VLISPpassescontroltoAutoCADtodisplaythedialogbox.IfAutoCADfindssyntacticalerrors,itdisplaysoneormoremessagewindowsidentifyingtheerrors.

IfAutoCADdetectsDCLerrorsandyouareunabletofigureouthowtofixthem,copythegpdialog.dclfileinyourTutorial\VisualLISP\Lesson4directoryandsaveitintheSupportdirectory.

Pleasesendusyourcommentaboutthispage

Page 91: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>

InteractingwiththeDialogBoxfromAutoLISPCode

YounowneedtoprogramyourAutoLISPfunctiontointeractwiththedialogbox.Thestubbed-outfunction,gp:getDialogInput,iswherethisactivitywilltakeplace.Thisfunctionnowlivesinthegp-io.lspfile,whichyouearlierextractedfromgpmain.lsp.

Developingadialogboxinterfacecanbeconfusingthefirstfewtimesyoudoit.Itinvolvesplanningaheadandaskingyourselfsuchquestionsas:

Doesthedialogboxneedtobesetupwithdefaultvalues?

Whathappenswhentheuserchoosesabuttonorentersavalue?

WhathappenswhentheuserchoosesCancel?

Ifthedialog(.dcl)fileismissing,whatneedstooccur?

Topicsinthissection

SettingUpDialogValuesLoadingtheDialogFileLoadingaSpecificDialogintoMemoryInitializingtheDefaultDialogValuesAssigningActionstoTilesStartingtheDialogUnloadingtheDialogDeterminingWhattoDoNextPuttingtheCodeTogetherUpdatingaStubbed-OutFunction

Page 92: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Pleasesendusyourcommentaboutthispage

Page 93: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

SettingUpDialogValues

Whenyourunthecompletegardenpathapplication,noticethatthedialogboxalwaysstartsupwithActiveXasthedefaultobjectcreationmethodandLightweightasthepolylinestyle.Somethingmoreinterestingoccurswiththedefaulttilesize—thevalueschangedependingonthewidthofthepath.Thefollowingcodefragmentshowshowtosetupthedefaultvaluestobedisplayedinthedialogbox:

(setqobjectCreateMethod"ACTIVEX"

plineStyle"LIGHT"

tilerad(/pathWidth15.0)

tilespace(/tilerad5.0)

dialogLoadedT

dialogShowT

);_endofsetq

Forthemoment,don'tworryaboutwhatpurposethedialogLoadedanddialogShowvariablesserve.Thisbecomesapparentinthenexttwosections.

Pleasesendusyourcommentaboutthispage

Page 94: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

LoadingtheDialogFile

YourprogramfirstneedstoloadtheDCLfileusingtheload_dialogfunction.ThisfunctionsearchesfordialogfilesaccordingtotheAutoCADsupportfilesearchpath,unlessyouspecifyafullpathname.

Foreveryload_dialogfunctionthereshouldbeacorrespondingunload_dialogfunctionlaterinthecode.Youwillseethisinamoment.Fornow,takealookathowyouneedtoloadinyourdialog:

;;Loadthedialogbox.Setuperrorcheckingtomakesure

;;thedialogfileisloadedbeforecontinuing

(if(=-1(setqdcl_id(load_dialog"gpdialog.dcl")))

(progn

;;There'saproblem-displayamessageandsetthe

;;dialogLoadedflagtonil

(princ"\nCannotloadgpdialog.dcl")

(setqdialogLoadednil)

);_endofprogn

);_endofif

ThedialogLoadedvariableindicatesifthedialogloadedsuccessfully.Inthecodewhereyousetuptheinitialvaluesforthedialogbox,yousetdialogLoadedtoaninitialvalueofT.Asyoucanseeinthecodefragmentabove,dialogLoadedissettonilifthereisaproblemwiththeload.

Pleasesendusyourcommentaboutthispage

Page 95: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

LoadingaSpecificDialogintoMemory

ItwasnotedearlierthatasingleDCLfilemaycontainmultipledialogboxdefinitions.Thenextstepinusingadialogistospecifywhichdialogboxdefinitiontodisplay.Thefollowingcodedemonstratesthis:

(if(anddialogLoaded

(not(new_dialog"gp_mainDialog"dcl_id))

);_endofand

(progn

;;There'saproblem...

(princ"\nCannotshowdialoggp_mainDialog")

(setqdialogShownil)

);_endofprogn

);_endofif

Noticehowtheandfunctionisusedtotestifthedialogwasloadedandifthecalltonew_dialogwassuccessful.Iftherearemultipleexpressionsevaluatedwithinanandfunctioncall,evaluationofsubsequentexpressionsisterminatedwiththefirstexpressionthatevaluatestonil.Inthiscase,ifthedialogLoadedflagisnil(meaningtheloadfunctionintheprevioussectionfailed),VLISPdoesnotattempttoperformthenew_dialogfunction.

NoticethatthecodealsoaccountsforthepossibilitythatsomethingmightnotbeworkingproperlywiththeDCLfile,andsetsthedialogShowvariabletonilifthatisthecase.

Thenew_dialogfunctionsimplyloadsthedialogintomemory—itdoesnotdisplayit.Thestart_dialogfunctiondisplaysthedialogbox.Alldialogboxinitialization,suchassettingtilevalues,creatingimagesorlistsforlistboxes,andassociatingactionswithspecifictilesmusttakeplaceafterthenew_dialogcallandbeforethestart_dialogcall.

Page 96: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Pleasesendusyourcommentaboutthispage

Page 97: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

InitializingtheDefaultDialogValues

Ifeverythingworkedsuccessfullyinloadingthedialog,youarereadytostartsettingupthevaluesthatwillbedisplayedtousers.AsuccessfulloadisindicatediftheflagvariablesdialogLoadedanddialogShowarebothT(true).

Nowsettheinitialvaluesforthetileradiusandspacing.Theset_tilefunctionassignsavaluetoatile.Aneditboxdealswithstringsratherthannumbers,soyouneedtousethertos(convertRealTOString)functiontoconvertyourtilesizevariablevaluesintostringsindecimalformatwithaprecisionoftwodigits.Thefollowingcodehandlesthisconversion:

(if(anddialogLoadeddialogShow)

(progn

;;Settheinitialstateofthetiles

(set_tile"gp_trad"(rtostileRad22))

(set_tile"gp_spac"(rtostileSpace22))

Pleasesendusyourcommentaboutthispage

Page 98: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

AssigningActionstoTiles

ADCLdefinitiondoesnothingmorethandefinealifelessdialogbox.YouconnectthislifelessdialogboxtoyourdynamicAutoLISPcodewiththeaction_tilefunction,asdemonstratedbythefollowingcode:

;;Assignactions(thefunctionstobeinvoked)todialogbuttons

(action_tile

"gp_lw"

"(setqplineStyle\"Light\")"

)

(action_tile

"gp_hw"

"(setqplineStyle\"Pline\")"

)

(action_tile

"gp_actx"

"(setqobjectCreateMethod\"ActiveX\")"

)

(action_tile

"gp_emake"

"(setqobjectCreateMethod\"Entmake\")"

)

(action_tile

"gp_cmd"

"(setqobjectCreateMethod\"Command\")"

)

(action_tile"cancel""(done_dialog)(setqUserClicknil)")

(action_tile

"accept"

(strcat"(progn(setqtileRad(atof(get_tile\"gp_trad\")))"

"(setqtileSpace(atof(get_tile\"gp_spac\")))"

"(done_dialog)(setqUserClickT))"

)

)

NoticeallthequotesaroundtheAutoLISPcode.WhenyouwriteanAutoLISPaction_tilefunction,yourcodeisessentiallytellingatile,“here,remember

Page 99: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

thisstring,thenpassitbacktomewhentheuserselectsyou.”Thestring(anythingwithindouble-quotationmarks)isdormantuntiltheuserselectsthetile.Atthattime,thetilepassesthestringtoAutoCAD,whichconvertsthestringintofunctioningAutoLISPcodeandexecutesthecode.

Forexample,considerthefollowingaction_tileexpression,whichisconnectedtothelightweightpolylineradiobutton:

(action_tile

"gp_lw"

"(setqplineStyle\"Light\")"

)

Thecodeassignsthestring"(setqplineStyle\"Light\")"totheradiobutton.Whenauserpicksthebutton,thestringispassedbacktoAutoCADandtransformeddirectlyintothefollowingAutoLISPexpression:

(setqplineStyle"Light")

Lookatonemorecodefragment.Thefollowingistheaction_tileexpressionassignedtotheOKbutton:

(action_tile

"accept"

(strcat"(progn(setqtileRad(atof(get_tile\"gp_trad\")))"

"(setqtileSpace(atof(get_tile\"gp_spac\")))"

"(done_dialog)(setqUserClickT))"

)

WhenauserchoosestheOKbutton,thelengthystringassignedtothebuttonispassedtoAutoCADandturnedintothefollowingAutoLISPcode:

(progn

(setqtileRad(atof(get_tile"gp_trad")))

(setqtileSpace(atof(get_tile"gp_spac")))

(done_dialog)

(setqUserClickT)

)

Thiscodedoesseveralthings:Itretrievesthecurrentvaluesfromthetileswhosekeyvaluesaregp_trad(thetileradius)andgp_spac(thetilespacingvalue).Thenatofconvertsthenumberstringintoarealnumber.Thedialogisterminatedwiththedone_dialogfunction,andavalueofT,ortrue,is

Page 100: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

assignedtothevariableUserClick.

You'redoneassigningactionstothebuttons.Thenextthingtodoistoputitallinmotion.

Pleasesendusyourcommentaboutthispage

Page 101: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

StartingtheDialog

Thestart_dialogfunctiondisplaysadialogboxandacceptsuserinput.Thestart_dialogfunctionrequiresnoarguments.

(start_dialog)

Controlpassestouserswhenyouissuestart_dialog.Userscanmakechoiceswithinthedialogbox,untiltheychoosetheOKorCancelbuttons.

Pleasesendusyourcommentaboutthispage

Page 102: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

UnloadingtheDialog

WhenauserchoosestheOKorCancelbutton,youneedtounloadthedialog.Likestart_dialog,unload_dialogisanothersimplefunction.

(unload_dialogdcl_id)

Pleasesendusyourcommentaboutthispage

Page 103: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

DeterminingWhattoDoNext

IftheuserchoseOK,youmustbuildalistcontainingthevaluessetbytheuser'sinteractionwiththedialog.Thislistiswhatgp:getDialogInputwillreturntoitscallingfunction.IftheuserchoseCancel,thefunctionreturnsnil:

(ifUserClick;UserclickedOk

;;Buildtheresultingdata

(progn

(setqResult(list

(cons42tileRad)

(cons43TileSpace)

(cons3objectCreateMethod)

(cons4plineStyle)

)

)

)

)

Pleasesendusyourcommentaboutthispage

Page 104: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

PuttingtheCodeTogether

Withtheexamplesabove,andafewadditionallines,youhavethecodeneededtocompletethegp:getDialogInputfunction.

Toputgp:getDialogInputtogether

1. Openyourcopyofgp-io.lspinaVLISPtexteditorwindow.

2. Deletethecodeingp:getDialogInput(thedefungp:getDialogInputstatementandeverythingafterit).

3. Enterthefollowingdefunstatementasthefirstlineofcodeinthegp:getDialogInputfunction:

(defungp:getDialogInput(pathWidth/dcl_idobjectCreateMethod

plineStyletileradtilespaceresultUserClick

dialogLoadeddialogShow)

Thefunctionexpectsasingleargument(pathwidth),andestablishesanumberoflocalvariables.

4. Followingthecodeyouaddedinstep3,enterthesamplecodefromeachofthefollowingsections:

SettingUpDialogValues

LoadingtheDialogFile

LoadingaSpecificDialogintoMemory

InitializingtheDefaultDialogValues

AssigningActionstoTilesNote EnterjustthefirstcodeexamplefromAssigningActionstoTiles

Page 105: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

notthefragmentsintheexplanationsthatfollow.Thosefragmentsjustrepeatpiecesoftheexample.

StartingtheDialog

UnloadingtheDialog

DeterminingWhattoDoNext

5. Afterthelastlineofcode,addthefollowing:

)

)

Result;

);_endofdefun

6. FormatthecodeyouenteredbychoosingTools FormatCodeinEditorfromtheVLISPmenu.

Pleasesendusyourcommentaboutthispage

Page 106: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

UpdatingaStubbed-OutFunction

Youhavenowrevisedthegp:getDialogInputfunction.Wheneveryoumodifyastubbed-outfunction,youshouldalwayscheckacoupleofthings:

Hasthedefunstatementchanged?Thatis,doesthefunctionstilltakethesamenumberofarguments?

Doesthefunctionreturnsomethingdifferent?

Inthecaseofgp:getDialogInput,theanswertobothquestionsisyes.Thefunctionnowacceptstheparameterofthepathwidth(tosetthedefaulttilesizeandspacing).AndinsteadofreturningT,whichisthevaluethestubbed-outversionofthefunctionreturned,gp:getDialogInputnowreturnsanassociationlistcontainingfournewvalues.

Bothchangesaffectthecodethatcallsthefunctionandthecodethathandlesthereturnvaluesfromthefunctions.ReplaceyourpreviousversionoftheC:GPathfunctioningpmain.lspwiththefollowingcode:

(defunC:GPath(/gp_PathDatagp_dialogResults)

;;Asktheuserforinput:firstforpathlocationand

;;direction,thenforpathparameters.Continueonlyifyou

;;havevalidinput.Storethedataingp_PathData.

(if(setqgp_PathData(gp:getPointInput))

(if(setqgp_dialogResults(gp:getDialogInput(cdr(assoc40

gp_PathData))))

(progn

;;Nowtaketheresultsofgp:getPointInputandappendthis

;;totheaddedinformationsuppliedbygp:getDialogInput.

(setqgp_PathData(appendgp_PathDatagp_DialogResults))

;;Atthispoint,youhavealltheinputfromtheuser.

;;Drawtheoutline,storingtheresultingpolyline

;;"pointer"inthevariablecalledPolylineName.

(setqPolylineName(gp:drawOutlinegp_PathData))

);_endofprogn

Page 107: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(princ"\nFunctioncancelled.")

);_endofif

(princ"\nIncompleteinformationtodrawaboundary.")

);_endofif

(princ);exitquietly

);_endofdefun

TakealookattheboldfacelinesintherevisionofthemainC:GPathfunction.Therearetwoessentialchangestomaketheprogramworkcorrectly:

Whenthegp:getDialogInputfunctionisinvoked,thepathwidthispassedtoit.Thisisdonebyextractingthevalueassociatedwiththekey40indexofthegp_PathDataassociationlist.

Theassociationlistreturnedbygp:getPointInputisassignedtoavariablecalledgp_dialogResults.Ifthisvariablehasavalue,itscontentneedstobeappendedtotheassociationlistvaluesalreadystoredingp_PathData.

Thereareadditionalchangesinthecoderesultingfromthereplacementofplaceholdersinthestubbed-outversion.Theeasiestthingtodoiscopythiscodefromtheonlinetutorialandpasteitintoyourfile.

Pleasesendusyourcommentaboutthispage

Page 108: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>

ProvidingaChoiceofBoundaryLineType

Onerequirementspecifiedforthegardenpathapplicationwastoallowuserstodrawtheboundaryoutlineaseitheralightweightpolylineoranold-stylepolyline.Thefirstversionofgp:drawOutlineyouwrotealwaysusedalightweightpolylinetodrawtheboundary.Nowthatthedialogboxinterfaceisreadytogo,youcanbuildintheoptionfordrawinganold-stylepolylineaswell.Toaccomplishthis,gp:drawOutlinemustdeterminewhatkindofpolylinetodraw,andthenitmustdrawit.

Thenecessarychangestogp:drawOutlineareincludedinthefollowingcodefragment.Makethemodificationfromthegpdraw.lspfileindicatedinbold:

(setqPathAngle(cdr(assoc50BoundaryData))

Width(cdr(assoc40BoundaryData))

HalfWidth(/Width2.00)

StartPt(cdr(assoc10BoundaryData))

PathLength(cdr(assoc41BoundaryData))

angp90(+PathAngle(Degrees->Radians90))

angm90(-PathAngle(Degrees->Radians90))

p1(polarStartPtangm90HalfWidth)

p2(polarp1PathAnglePathLength)

p3(polarp2angp90Width)

p4(polarp3(+PathAngle(Degrees->Radians180))

PathLength)

poly2Dpoints(apply'append

(mapcar'3dPoint->2dPoint(listp1p2p3p4))

)

poly3Dpoints(mapcar'float(appendp1p2p3p4))

;;getthepolylinestyle

plineStyle(strcase(cdr(assoc4BoundaryData)))

);_endofsetq

;;AddpolylinetothemodelspaceusingActiveXautomation

(setqpline(if(=plineStyle"LIGHT")

;;createalightweightpolyline

(vla-addLightweightPolyline

*ModelSpace*;GlobalDefinitionforModelSpace

(gp:list->variantArraypoly2Dpoints);dataconversion

Page 109: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

);_endofvla-addLightweightPolyline

;;orcreateanold-stylepolyline

(vla-addPolyline

*ModelSpace*

(gp:list->variantArraypoly3Dpoints);dataconversion

);_endofvla-addPolyline

);_endofif

);_endofsetq

Typingthechangesintoyourcodecanbeverytricky,asyounotonlyneedtoaddcodebutalsotodeletesomeexistinglinesandrearrangeothers.Itisrecommendedyoucopytheentiresetqstatementfromtheonlinetutorialandpasteitintoyourcode.

Pleasesendusyourcommentaboutthispage

Page 110: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>

CleaningUp

Ifyouhavenotdonesoalready,deletethefollowingcodefromtheC:GPathfunctioningpmain.lsp:

(princ"\nThegp:drawOutlinefunctionreturned<")

(princPolylineName)

(princ">")

(Alert"Congratulations-yourprogramiscomplete!")

Youhadbeenusingthiscodeasaplaceholder,butnowthatgp:drawOutlineisfunctioning,younolongerneedit.

Pleasesendusyourcommentaboutthispage

Page 111: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>

RunningtheApplication

Beforerunningyourprogram,saveallthefilesyouchanged,ifyouhavenotalreadydoneso.YoucanchooseFile SaveAllfromtheVLISPmenu,orusetheALT+SHIFT+Skeyboardshortcuttosaveallyouropenfiles.

ThenextthingyoumustdoisreloadallthefilesinVLISP.

Toloadandrunallthefilesinyourapplication

1. Iftheprojectfileyoucreatedearlierinthislessonisnotalreadyopen,chooseProject OpenProjectfromtheVLISPmenu,thenentertheprojectfilenamegpath;donotincludethe.prjextension.IfVLISPdoesnotfindtheprojectfile,choosetheBrowsebuttonandchoosethefilefromtheOpenProjectdialogbox.ClickOpen.

2. ChoosetheLoadSourceFilesbuttonintheprojectwindow.

3. Enterthe(C:GPath)commandattheVLISPConsoleprompttoruntheprogram.Ifyouhavesomedebuggingtodo,tryusingthetoolsyoulearnedinLessons2and3.Andremember,ifallelsefails,youcanalwayscopythecodefromtheTutorial\VisualLISP\Lesson4directory.

Also,trydrawingthepathusingbothlightweightandold-stylepolylines.Afterdrawingthepaths,usetheAutoCADlistcommandtodeterminewhetherornotyourprogramisdrawingthecorrectentitytypes.

Pleasesendusyourcommentaboutthispage

Page 112: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

CreatingaProjectandAddingtheInterface>

WrappingUpLesson4

Inthislesson,you

Modularizedyourcodebydividingitamongfourfiles.

OrganizedyourcodemodulesinaVLISPproject.

Learnedtodefineadialogboxwithdialogcontrollanguage(DCL).

AddedAutoLISPcodetosetupandhandleinputinthedialogbox.

Modifiedyourcodetoprovideuserswithachoiceofboundarylinetype.

Nowyouhaveaprogramthatdrawsagardenpathboundary.Inthenextlesson,youwilladdthetilestothegardenpath.Intheprocess,youwillbeintroducedtomoreVLISPprogramdevelopmenttools.

Pleasesendusyourcommentaboutthispage

Page 113: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles

Bytheendofthislesson,yourapplicationwillmeetthebasicrequirementsstatedinLesson1.Youwilladdthefunctionalityfordrawingtileswithintheboundaryofthegardenpathandprovidethisfunctionusingseveraldifferentmethodsofentitycreation.Youwillalsolearnsomekeyboardshortcutsandneweditingtools.

Topicsinthissection

IntroducingMoreVisualLISPEditingToolsAddingTilestotheGardenPathTestingtheCodeWrappingUpLesson5

Pleasesendusyourcommentaboutthispage

Page 114: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>

IntroducingMoreVisualLISPEditingTools

Openyourcopyofgpdraw.lspinaVisualLISP®texteditorwindow,ifthefileisnotalreadyopen.ThereareacoupleofthingsaboutthiscodethataretypicalofmuchofthecodeyouwillbedevelopingwithVLISP.First,therearemanyparenthesesandparentheseswithinparentheses.Second,therearemanyfunctioncalls,andsomeofthosefunctionshaveverylongnames(vla-addLightweightPolyline,forexample).VLISPprovidessomeeditingtoolstohelpyoudealwiththesecommonfeaturesofAutoLISP®code.

Topicsinthissection

MatchingParenthesesCompletingaWordAutomaticallyCompletingaWordbyAproposGettingHelpwithaFunction

Pleasesendusyourcommentaboutthispage

Page 115: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>IntroducingMoreVisualLISPEditingTools>

MatchingParentheses

VLISPprovidesaparenthesismatchingfeaturetohelpyoufindthecloseparenthesisthatcorrespondstoanopenparenthesis.

Tomatchanopenparenthesiswithitscorrespondingcloseparenthesis

1. Placeyourcursorinfrontoftheopeningparenthesisthatprecedesthesetqfunctioncall.

2. PressCTRL+SHIFT+].(Double-clickingalsodoesthetrick.)

VLISPfindstheclosingparenthesisthatmatchestheoneyouchose,andselectsallthecodeinbetween.Notonlydoesthisensureyoutypedinthecorrectnumberofparentheses,italsomakesiteasytocopyorcuttheselectedtext.ThismighthavecomeinhandywhenyouupdatedthiscallattheendofLesson4.

Whyelsemightyouwanttodothis?YoucancopysomecodetotheVLISPConsolewindow,pasteitthere,andtryitout.Ormaybeyouhavefiguredouthowtoreplace50linesofcodewiththreereallymarvelouslinesofmuchbettercode.Youcanquicklyselecttheoldcodeusingtheparenthesesmatchingtool,theneliminateitwithasinglekeystroke.ItisalotquickertoletVLISPfindanentireblockthanforyoutohuntdowneverylastclosingparenthesis.

Thereisacorrespondingkeycommandformatchingandselectingbackward.Totrythis,putyourcursorafteraclosingparenthesis,theneitherdouble-clickorpressCTRL+SHIFT+[.VLISPsearchesforthecorrespondingopeningparenthesis,andselectsitalongwiththeenclosedcode.

BothcommandsarealsoavailablebychoosingEdit ParenthesesMatchingfromtheVLISPmenu.

Pleasesendusyourcommentaboutthispage

Page 116: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>IntroducingMoreVisualLISPEditingTools>

CompletingaWordAutomatically

Imagineyouareaddingsomenewfunctionalitytoyourprogramusingthefollowingcode:

ObjectCreationStyle(strcase(cdr(assoc3BoundaryData)))

(if(equalObjectCreationStyle"COMMAND")

(progn

(setqfirstCenterPt(polarrowCenterPt(Degrees->Radians45)distanceOnPath))

(gp:Create_activeX_Circle)

)

)

(Don'tworryaboutwhatthiscodeactuallydoes,ifanything.Itisonlyanexamplethatincludesseverallongvariableandfunctionnames.)

VLISPcansaveyousomekeystrokesbycompletingwordsforyou.

TousetheVisualLISPCompleteWordbyMatchfeature

1. Scrolltothebottomofthegpdraw.lspfileandenterthefollowingcode:

ObjectCreationStyle(strcase(cdr(assoc3BoundaryData)))

(if(equalOb

2. PressCTRL+SPACEBAR.VLISPjustsavedyouseventeenkeystrokesasitsearchedwithinthecurrentfileandfoundtheclosestmatchtothelasttwolettersyoutyped.

3. Completethelineofcodesothatitlookslikethefollowing:

(if(equalObjectCreationStyle"COMMAND")

4. Addthefollowinglines:

(progn

Page 117: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(setqfirstCenterPt(p

5. PressCTRL+SPACEBAR.VLISPmatchesthemostrecent“p”word,whichhappenstobeprogn.However,thewordyouneedispolar.IfyoukeeppressingCTRL+SPACEBAR,VLISPcyclesthroughallthepossiblematchesinyourcode.Eventually,itwillcomearoundtopolar.

6. Deleteallthecodeyoujustentered;itwasfordemonstrationpurposesonly.TheCompleteWordbyMatchfeatureisalsoavailablefromtheVLISPSearchmenu.

Pleasesendusyourcommentaboutthispage

Page 118: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>IntroducingMoreVisualLISPEditingTools>

CompletingaWordbyApropos

IfyouhaveworkedwithAutoLISPbefore,youmayhavehadtotypeinanexpressionsimilartotheoneshownbelow:

(setqmyEnt(ssnamemySelectionSetssIndex))

Often,itisconfusingtokeeptrackofalltheselectionsetfunctions:ssname,ssget,sslength,andsoon.VLISPcanhelp,usingitsCompleteWordbyAproposfeature.

TousetheVisualLISPCompleteWordbyAproprosfeature

1. Scrolltothebottomofthegpdraw.lspfileandenterthefollowingonablankline:

(setqmyEnt(ent

2. PressCTRL+SHIFT+SPACEBAR.VLISPdisplaysalistofallAutoLISPsymbolsthatbeginwiththelettersent.Usethecursorkeys(theupanddownarrowkeys)tomovethroughthelist.SelectENTGET,thenpressENTER.VLISPreplacestheentyoutypedwithENTGET.

3. Deletethecode.

Pleasesendusyourcommentaboutthispage

Page 119: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>IntroducingMoreVisualLISPEditingTools>

GettingHelpwithaFunction

Thecodethataddsalightweightpolylinetothedrawingcallsafunctionnamedvla-addLightweightPolyline.Notonlyisthatalengthytermtowrite,butthereareseveralfunctionswhosenamesbeginwithvla-addthatyouwillusetocreateentities.Ratherthanconsultingamanualtolookupthefunctionnameeverytimeyoucreateaprogram,letVLISPhelp.

Togethelpwithusingafunction

1. Enterthefollowingonablankline:

(vla-add

2. PressCTRL+SHIFT+SPACEBAR.

3. Scrollthroughthelistuntilyoufindvla-addLightweightPolyline.

4. Double-clickonvla-addLightweightPolyline.VLISPdisplaystheSymbolServicedialogboxfortheselectedfunction.

5. ChoosetheHelpbuttonintheSymbolServicedialogbox.(ForActiveX®functions,youwillbedirectedtotheActiveXandVBAReference.)

6. Deletethechangesyoumadetogpdraw.lsp;thesewerefordemonstrationpurposesonly.Also,closetheSymbolServiceandAproposwindows.

Pleasesendusyourcommentaboutthispage

Page 120: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic
Page 121: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>

AddingTilestotheGardenPath

Younowhaveapathboundaryandarereadytofillitwithtiles.Youwillneedtoapplysomelogicandworkthroughalittlegeometry.

Topicsinthissection

ApplyingSomeLogicApplyingSomeGeometryDrawingtheRowsDrawingtheTilesinaRowLookingattheCode

Pleasesendusyourcommentaboutthispage

Page 122: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>AddingTilestotheGardenPath>

ApplyingSomeLogic

Onethingyouneedtodoisdeterminehowtospaceoutthetilesanddrawthem.Ifthiswereasimplerectilineargridoftiles,youcouldusetheAutoCAD®

ARRAYcommandtofillinthetiles.Butforthegardenpath,youneedtohaveeachrowoftilesoffsetfromthepreviousrow.

Thisrow-offsetpatternisarepeatingpattern.Thinkofhowyoumightgoaboutlayingthetilesifyouwerebuildingtheactualpath.Youwouldprobablybeinclinedtostartatoneendandjustkeeplayingdownrowsuntiltherewasn'tanymorespaceleft.

Hereisthelogicinpseudo-code:

Atthestartingpointofthepath

Figureouttheinitialrowoffsetfromcenter(eithercenteredon

thepathoroffsetbyone"tilespace").

Whilethespaceoftheboundaryfilledislessthanthespaceto

fill,

Drawarowoftiles.

Page 123: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Resetthenextstartpoint(incrementedbyone"tilespace").

Addthedistancefilledbythenewrowtotheamountofspace

filled.

Toggletheoffset(ifitiscentered,setitupoff-center,or

viceversa).

Gobacktothestartoftheloop.

Pleasesendusyourcommentaboutthispage

Page 124: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>AddingTilestotheGardenPath>

ApplyingSomeGeometry

Thereareonlyafewdimensionsyouneedtoknowtodrawthegardenpath.Thehalf-widthiseasy:itisjusthalfthewidthofthepath.Youalreadydefinedthecodetoobtainthiswidthfromusersandsaveditinanassociationlist.

Tilespacingisalsoeasy;itistwicetheradius(thatis,thediameter)plusthespacebetweenthetiles.Thedimensionsarealsoobtainedfromusers.

Rowspacingisalittletrickier,unlessyouarereallysharpwithtrigonometry.Hereistheformula:

RowSpacing=(TileDiameter+SpacebetweenTiles)*(thesine

of60degrees)

Pleasesendusyourcommentaboutthispage

Page 125: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>AddingTilestotheGardenPath>

DrawingtheRows

Seeifyoucanmakesenseofthefollowingfunction.Compareittothepseudo-codeandtrytocatchthegeometriccalculationsjustdescribed.TheremaybeafewAutoLISPfunctionsthatarenewtoyou.Ifyouneedhelpwiththesefunctions,refertotheAutoLISPReference.Fornow,justreadthecode;donotwriteanything.

(defungp:Calculate-and-Draw-Tiles(BoundaryData/PathLength

TileSpaceTileRadiusSpaceFilledSpaceToFill

RowSpacingoffsetFromCenter

rowStartPointpathWidthpathAngle

ObjectCreationStyleTileList)

(setqPathLength(cdr(assoc41BoundaryData))

TileSpace(cdr(assoc43BoundaryData))

TileRadius(cdr(assoc42BoundaryData))

SpaceToFill(-PathLengthTileRadius)

RowSpacing(*(+TileSpace(*TileRadius2.0))

(sin(Degrees->Radians60))

);_endof*

SpaceFilledRowSpacing

offsetFromCenter0.0

offsetDistance(/(+(*TileRadius2.0)TileSpace)2.0)

rowStartPoint(cdr(assoc10BoundaryData))

pathWidth(cdr(assoc40BoundaryData))

pathAngle(cdr(assoc50BoundaryData))

ObjectCreationStyle(strcase(cdr(assoc3BoundaryData)))

);_endofsetq

;;Compensateforthefirstcalltogp:calculate-Draw-tileRow

;;intheloopbelow.

(setqrowStartPoint

(polarrowStartPoint

(+pathAnglepi)

(/TileRadius2.0)

);_endofpolar

);_endofsetq

;;Draweachrowoftiles.

(while(<=SpaceFilledSpaceToFill)

;;Getthelistoftilescreated,addingthemtoourlist.

Page 126: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(setqtileList(appendtileList

(gp:calculate-Draw-TileRow

(setqrowStartPoint

(polarrowStartPoint

pathAngle

RowSpacing

);_endofpolar

);_endofsetq

TileRadius

TileSpace

pathWidth

pathAngle

offsetFromCenter

ObjectCreationStyle

);_endofgp:calculate-Draw-TileRow

);_endofappend

;;Calculatethedistancealongthepathforthenextrow.

SpaceFilled(+SpaceFilledRowSpacing)

;;Alternatebetweenazeroandapositiveoffset

;;(causesalternaterowstobeindented).

offsetFromCenter

(if(=offsetFromCenter0.0)

offsetDistance

0.0

);_endofif

);_endofsetq

);_endofwhile

;;Returnthelistoftilescreated.

tileList

);_endofdefun

Acoupleofsectionsfromthecodemayneedalittleextraexplanation.

Thefollowingcodefragmentoccursrightbeforethewhileloopbegins:

;;Compensatefortheveryfirststartpoint!!

(setqrowStartPoint(polarrowStartPoint

(+pathAnglepi)(/TileRadius2.0)))

Therearethreepiecestothepuzzleoffiguringoutthelogicbehindthisalgorithm:

TherowStartPointvariablestartsitslifewithinthegp:Calculate-and-Draw-Tilesfunctionbybeingassignedthepointtheuserselectedasthestartpointofthepath.

Theveryfirstargumentpassedtothegp:calculate-Draw-TileRowfunctiondoesthefollowing:

Page 127: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(setqrowStartPoint(polarrowStartPoint

pathAngleRowSpacing))

Anotherwayofstatingthisis:Atthetimethegp:calculate-Draw-TileRowfunctioniscalled,therowStartPointvariableissettooneRowSpacingdistancebeyondthecurrentrowStartPoint.

TherowStartPointargumentisusedwithingp:calculate-Draw-TileRowasthestartingpointforthecentersofthecirclesintherow.

TocompensatefortheinitialforwardshiftingoftherowStartPointduringthedrawingofthefirstrow(thatis,thefirstcyclethroughthewhileloop),youwillwanttoshiftrowStartPointslightlyintheoppositedirection.Theaimistoavoidtheappearanceofalargemarginofemptyspacebetweenthepathboundaryandthefirstrow.HalftheTileRadiusisasufficientamountbywhichtomovethepoint.ThiscanbeachievedbyusingpolartoprojectrowStartPointalongavectororiented180degreesfromthePathAngle.Ifyouthinkaboutit,thisplacesthepointtemporarilyoutsidethepathboundary.

Thenextfragment(modifiedforreadability)maybealittlepuzzling:

(setqtileList(appendtileList

(gp:calculate-Draw-TileRow

(setqrowStartPoint

(polarrowStartPointpathAngleRowSpacing)

);_endofsetq

TileRadiusTileSpacepathWidthpathAngle

offsetFromCenterObjectCreationStyle

)))

Inessence,thereissetqwrappedaroundanappendwrappedaroundthecalltogp:calculate-Draw-TileRow.

Thegp:calculate-Draw-TileRowfunctionwillreturntheObjectIDsforeachtiledrawn.(TheObjectIDpointstothetileobjectinthedrawing.)Youaredrawingthetilesrowbyrow,sothefunctionreturnstheObjectIDsofonerowatatime.TheappendfunctionaddsthenewObjectIDstoanyexistingObjectIDsstoredintileList.

Neartheendofthefunction,youcanfindthefollowingcodefragment:

(setqoffsetFromCenter

Page 128: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(if(=offsetFromCenter0.0)

offsetDistance

0.0

)

)

Thisistheoffsettoggle,whichdetermineswhethertherowbeingdrawnshouldbeginwithacirclecenteredonthepathoroffsetfromthepath.Thepseudo-codeforthisalgorithmfollows:

Settheoffsetamounttothefollowing:

Iftheoffsetiscurrentlyzero,setittotheoffsetdistance;

Otherwise,setitbacktozero.

Pleasesendusyourcommentaboutthispage

Page 129: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>AddingTilestotheGardenPath>

DrawingtheTilesinaRow

Nowthatyouhavethelogicfordrawingthepath,thenextstepistofigureouthowtodrawthetilesineachrow.Inthefollowingdiagram,therearetwocasesshown:arowwheretheoffsetfromthecenterofthepathisequalto0.0,andacasewheretheoffsetisnotequaltozero.Takealookatthediagram,thenreadthepseudo-codethatfollows.

SetupvariablesforStartPoint,angp90,angm90,andsoon.

SetthevariableFirstCenterPointtotheStartPoint+offsetamount

(whichmaybe0.0).

SettheinitialvalueofTileCenterPttoFirstCenterPoint.

(Comment:Beginbydrawingthecirclesintheangp90direction.)

WhilethedistancefromtheStartPointtotheTileCenterPtislessthantheHalfWidth:

Drawacircle(addingtotheaccumulatinglistofcircles).

SetTileCenterPttothenexttilespaceincrementintheangp90

direction.

EndWhile

ResettheTileCenterPointtotheFirstCenterPoint+thetilespaceincrementatangm90.

WhilethedistancefromtheStartPointtotheTileCenterPtislessthantheHalfWidth:

Drawacircle(addingtotheaccumulatinglistofcircles).

SetTileCenterPttothenexttilespaceincrementintheangm90

direction.

EndWhile

Returnthelistofcircles.

Page 130: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Pleasesendusyourcommentaboutthispage

Page 131: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>AddingTilestotheGardenPath>

LookingattheCode

Nowlookatthecodeforthegp:calculate-Draw-TileRowfunction:

(defungp:calculate-Draw-TileRow(startPointTileRadius

TileSpacepathWidthpathAngleoffsetFromCenter

ObjectCreationStyle/HalfWidthTileDiameter

ObjectCreationFunctionangp90angm90

firstCenterPtTileCenterPtTileList)

(setqHalfWidth(-(/pathWidth2.00)TileRadius)

Tilespacing(+(*TileRadius2.0)TileSpace)

TileDiameter(*TileRadius2.0)

angp90(+PathAngle(Degrees->Radians90))

angm90(-PathAngle(Degrees->Radians90))

firstCenterPt(polarstartPointangp90offsetFromCenter)

tileCenterPtfirstCenterPt

ObjectCreationStyle(strcaseObjectCreationStyle)

ObjectCreationFunction

(cond

((equalObjectCreationStyle"ACTIVEX")

gp:Create_activeX_Circle

)

((equalObjectCreationStyle"ENTMAKE")

gp:Create_entmake_Circle

)

((equalObjectCreationStyle"COMMAND")

gp:Create_command_Circle

)

(T

(alert(strcat"ObjectCreationStyleinfunction

gp:calculate-Draw-TileRow"

"\nisinvalid.Contactdeveloperforassistance."

"\nObjectCreationStylesettoACTIVEX"

)

)

setqObjectCreationStyle"ACTIVEX")

)

)

)

;;Drawthecirclestotheleftofthecenter.

Page 132: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(while(<(distancestartPointtileCenterPt)HalfWidth)

;;Addeachtiletothelisttoreturn.

(setqtileList

(cons

(ObjectCreationFunctiontileCenterPtTileRadius)

tileList

)

)

;;Calculatethecenterpointforthenexttile.

(setqtileCenterPt

(polartileCenterPtangp90TileSpacing)

)

);_endofwhile

;;Drawthecirclestotherightofthecenter.

(setqtileCenterPt

(polarfirstCenterPtangm90TileSpacing))

(while(<(distancestartPointtileCenterPt)HalfWidth)

;;Addeachtiletothelisttoreturn.

(setqtileList

(cons

(ObjectCreationFunctiontileCenterPtTileRadius)

tileList

)

)

;;Calculatethecenterpointforthenexttile.

(setqtileCenterPt(polartileCenterPtangm90TileSpacing))

);_endofwhile

;;Returnthelistoftiles.

tileList

);_endofdefun

TheAutoLISPcodelogicfollowsthepseudo-code,withthefollowingaddition:

(setqObjectCreationFunction

(cond

((equalObjectCreationStyle"ACTIVEX")

gp:Create_activeX_Circle

)

((equalObjectCreationStyle"ENTMAKE")

gp:Create_entmake_Circle

)

((equalObjectCreationStyle"COMMAND")

gp:Create_command_Circle

)

(T

(alert

(strcat

"ObjectCreationStyleinfunctiongp:calculate-Draw-TileRow"

"\nisinvalid.Contactthedeveloperforassistance."

Page 133: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

"\nObjectCreationStylesettoACTIVEX"

);_endofstrcat

);_endofalert

(setqObjectCreationStyle"ACTIVEX")

)

);_endofcond

);_endofsetq

Rememberthespecificationtoallowuserstodrawthetiles(circles)usingeitherActiveX,theentmakefunction,orthecommandfunction?TheObjectCreationFunctionvariableisassignedoneofthreefunctions,dependingontheObjectCreationStyleparameter(passedfromC:GPathandthroughgp:Calculate-and-Draw-Tiles).Herearethethreefunctionsastheywillbedefinedingpdraw.lsp:

(defungp:Create_activeX_Circle(centerradius)

(vla-addCircle*ModelSpace*

(vlax-3d-pointcenter);converttoActiveX-compatible3Dpoint

radius

)

);_endofdefun

(defungp:Create_entmake_Circle(centerradius)

(entmake

(list(cons0"CIRCLE")(cons10center)(cons40radius))

)

(vlax-ename->vla-object(entlast))

)

(defungp:Create_command_Circle(centerradius)

(command"_CIRCLE"centerradius)

(vlax-ename->vla-object(entlast))

)

ThefirstfunctiondrawsacircleusinganActiveXfunctionandreturnsanActiveXobject.

Thesecondfunctiondrawsacircleusingentmake.ItreturnsanentitynameconvertedintoanActiveXobject.

Thethirdfunctiondrawsacircleusingcommand.ItalsoreturnsanentitynameconvertedintoanActiveXobject.

Pleasesendusyourcommentaboutthispage

Page 134: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>

TestingtheCode

Ifyou'vemadeitthisfar,youhaveearnedashortcut.

Totestthecode

1. ClosealltheactivewindowswithinVLISP,includinganyopenprojectwindows.

2. CopytheentirecontentsoftheTutorial\VisualLISP\Lesson5directorytoyourMyPathtutorialdirectory.

3. Opentheprojectfilegpath5.prjusingSelectProject OpenProjectfromtheVLISPmenubar.

4. Loadtheprojectsourcefiles.

5. Activate(switchto)theAutoCAD®windowandissuethegpathcommandtoruntheprogram.

6. Rungpathtodrawthegardenpaththreetimes,eachtimeusingadifferententitycreationmethod.Doyounoticeadifferenceinthespeedwithwhichthepathisdrawnwitheachmethod?

Pleasesendusyourcommentaboutthispage

Page 135: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

DrawingtheTiles>

WrappingUpLesson5

YoustartedthislessonbylearningVLISPeditingfeaturesthathelpedyou

Matchtheparenthesesinyourcode.

Findandcompleteafunctionname.

ObtaininformationinHelpforafunction.

Youfinishedthelessonbybuildingcodethatdrawsthetilesinthegardenpath.Younowhaveaprogramthatmeetstherequirementsestablishedattheverybeginningofthistutorial.

Atthispoint,youprobablyhaveacquiredenoughexperiencewithVLISPtoventureoffonyourown.Butifyouareuptoit,therearetwomorelessonsinthistutorialthatdemonstratetheuseofreactorfunctionsandotheradvancedfeaturesoftheVLISPenvironment.

Pleasesendusyourcommentaboutthispage

Page 136: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors

Inthislesson,youwilllearnaboutreactorsandhowtoattachthemtodrawingeventsandentities.ReactorsallowyourapplicationtobenotifiedbyAutoCAD®

whenparticulareventsoccur.Forexample,ifausermovesanentitythatyourapplicationhasattachedareactorto,yourapplicationwillreceivenotificationthattheentityhasmoved.Youcanprogramthistotriggeradditionaloperations,suchasmovingotherentitiesassociatedwiththeonetheusermoved,orperhapsupdatingatexttagthatrecordsrevisioninformationonthealtereddrawingfeature.Ineffect,itislikesettingupyourapplicationwithapagerandtellingAutoCADtobeeptheapplicationwhensomethinghappens.

Topicsinthissection

ReactorBasicsDesigningReactorsfortheGardenPathTestDrivingYourReactorsWrappingUpLesson6

Pleasesendusyourcommentaboutthispage

Page 137: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>

ReactorBasics

Areactorisanobjectyouattachtothedrawingeditor,ortospecificentitieswithinadrawing.Extendingthemetaphorofthepager,thereactorobjectisanautomaticdialerthatknowshowtocallyourpagerwhensomethingsignificanthappens.ThepagerwithinyourapplicationisanAutoLISP®functioncalledbythereactor;suchafunctionisknownasacallbackfunction.

Note ThecomplexityoftheapplicationcodeandthelevelofexpertiserequiredforthesefinaltwolessonsismuchhigherthanLessons1through5.Thereisagreatdealofinformationpresented,butitisnotallexplainedatthesamelevelofdetailasinthepreviouslessons.Ifyouareabeginner,don'tworryifyoudon'tgetitthefirsttime.ConsiderthisjustafirsttasteofsomeoftheverypowerfulbutmoretechnicallydifficultfeaturesofVisualLISP®.

Topicsinthissection

ReactorTypes

Pleasesendusyourcommentaboutthispage

Page 138: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>ReactorBasics>

ReactorTypes

TherearemanytypesofAutoCAD®reactors.EachreactortyperespondstooneormoreAutoCADevents.Reactorsaregroupedintothefollowingcategories:

EditorReactors

NotifyyourapplicationeachtimeanAutoCADcommandisinvoked.

LinkerReactors

NotifyyourapplicationeverytimeanObjectARX®applicationisloadedorunloaded.

DatabaseReactors

Correspondtospecificentitiesorobjectswithinadrawingdatabase.

DocumentReactors

NotifyyourapplicationinMDImodeofachangetothecurrentdrawingdocument,suchasopeningofanewdrawingdocument,activatingadifferentdocumentwindow,andchangingadocument'slockstatus.

ObjectReactors

Notifyyoueachtimeaspecificobjectischanged,copied,ordeleted.

Withtheexceptionofeditorreactors,thereisonetypeofreactorforeachreactorcategory.Editorreactorsencompassabroadclassofreactors:forexample,DXF™reactorsthatnotifyanapplicationwhenaDXFfileisimportedorexported,andMousereactorsthatnotifyofmouseeventssuchasdouble-clicks.

Withinthereactorcategories,therearemanyspecificeventstowhichyoucanattachareactor.AutoCADallowsuserstoperformmanydifferentkindsofactions,anditisuptoyoutodeterminetheactionsthatyouareinterestedin.Onceyouhavedonethis,youcanattachyourreactor“auto-dialer”totheevent,

Page 139: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

thenwritethecallbackfunctionthatistriggeredwhentheeventoccurs.

Pleasesendusyourcommentaboutthispage

Page 140: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>

DesigningReactorsfortheGardenPath

Toimplementreactorfunctionalityinthegardenpathapplication,startbyhandlingjustafewevents,ratherthantryingtocoverallpossibleuseractions.

Topicsinthissection

SelectingReactorEventsfortheGardenPathPlanningtheCallbackFunctionsPlanningforMultipleReactorsAttachingtheReactorsStoringDatawithaReactorUpdatingtheC:GPathFunctionAddingReactorCallbackFunctionsCleaningUpAfterYourReactors

Pleasesendusyourcommentaboutthispage

Page 141: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>DesigningReactorsfortheGardenPath>

SelectingReactorEventsfortheGardenPath

Forthetutorial,setthefollowinggoals:

Whenacornerpoint(vertex)ofthegardenpathboundaryisrepositioned,redrawthepathsothattheoutlineremainsrectilinear.Inaddition,redrawthetilesbasedonthenewsizeandshape.

Whenthegardenpathboundaryiserased,erasethetilesaswell.

Pleasesendusyourcommentaboutthispage

Page 142: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>DesigningReactorsfortheGardenPath>

PlanningtheCallbackFunctions

Foreachreactorevent,youmustplanthefunctionthatwillbeinvokedwhentheeventoccurs.Thefollowingpseudo-codeoutlinesthelogicalsequenceofeventsthatshouldoccurwhenusersdragoneofthepolylineverticestoanewlocation:

Defungp:outline-changed

Erasethetiles.

Determinehowtheboundarychanged.

Straightenuptheboundary.

Redrawnewtiles.

Endfunction

Thereisacomplication,though.Whentheuserbeginsdraggingtheoutlineofapolylinevertex,AutoCADnotifiesyourapplicationbyissuinga:vlr-modifiedevent.However,atthispointtheuserhasjustbegundraggingoneofthepolylinevertices.Ifyouimmediatelyinvokethegp:outline-changedfunction,youwillinterrupttheactionthattheuserisinthemidstof.Youwouldnotknowwherethenewvertexlocationwillbe,becausetheuserhasnotyetselecteditsposition.Andfinally,AutoCADwillnotallowyourfunctiontomodifythepolylineobjectwhiletheuserisstilldraggingit.AutoCADhasthepolylineobjectopenformodification,andleavesitopenuntiltheuserfinishesrepositioningtheobject.

Youneedtochangeyourapproach.Hereistheupdatedlogic:

Whentheuserbeginsrepositioningapolylinevertex,

Invokethegp:outline-changedfunction

Defungp:outline-changed

Setaglobalvariablethatstoresapointertothepolyline

beingmodifiedbytheuser

Endfunction

Whenthecommandcompletes,

Invokethegp:command-endedfunction

Defungp:command-ended

Erasethetiles

Page 143: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Getinformationonthepreviouspolylinevertexlocations

Getinformationonthenewpolylinevertexlocations

Redefinethepolyline(straightenitup)

Redrawthetiles

Endfunction

Whenausercompletesmodifyingapathoutline,AutoCADnotifiesyourapplicationbyissuinga:vlr-commandEndedevent,ifyouhaveestablishedaneditorreactor.

Theuseofaglobalvariabletoidentifythepolylinetheuserchangedisnecessarybecausethereisnocontinuitybetweenthegp:outline-changedandgp:command-endedfunctions.Inyourapplication,bothfunctionsareinvokedandexecutedindependentlyofoneanother.Theglobalvariablestoresimportantinformationsetupinonefunctionandaccessedintheother.

Nowconsiderwhattodoiftheusererasesthegardenpathboundary.Theultimateobjectiveistoeraseallthetiles.Thefollowingpseudo-codeoutlinesthelogic:

Whentheuserbeginstoerasetheboundary,

Invokethegp:outline-erasedfunction

Defungp:outline-erased

Setaglobalvariablethatstoresapointertothereactor

attachedtothepolylinecurrentlybeingerased

Endfunction

Whentheeraseiscompleted,

Invokethegp:command-endedfunction

Defungp:command-ended

Erasethetilesthatbelongedtothenow-deletedpolyline

Endfunction

Pleasesendusyourcommentaboutthispage

Page 144: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>DesigningReactorsfortheGardenPath>

PlanningforMultipleReactors

Usersmayhaveseveralgardenpathsonthescreen,andmaybeerasingmorethanone.Youneedtoplanforthispossibility.

Thereactorassociatedwithanentityisanobjectreactor.Ifthereareseveralentitiesinthedrawing,theremayalsobeseveralobjectreactors,oneforeachentity.Aspecificeditingevent,suchastheerasecommand,cantriggermanycallbacks,dependingonhowmanyoftheselectedentitieshavereactorsattached.Editorreactors,ontheotherhand,aresingularinnature.Yourapplicationshouldonlyattachasingle:vlr-commandEndedeventreactor.

Theeventsequenceforbothmodifications—changingavertexlocationanderasingapolyline—endsupwithactionsthatneedtobeperformedwithinthegp:command-endedfunction.Determinewhichsetofactionstoperformforeachcondition.Thefollowingpseudo-codeoutlinesthelogic:

Defungp:command-ended(2ndversion)

Retrievethepointertothepolyline(fromaglobalvariable)

Conditional:

Ifthepolylinehasbeenmodifiedthen:

Erasethetiles

Getinformationonthepreviouspolylinevertexlocations

Getinformationonthenewpolylinevertexlocations

Redefinethepolyline(straightenitup)

Redrawthetiles

Endconditionalexpression

Ifthepolylinehasbeenerasedthen:

Erasethetiles

Endconditionalexpression

EndConditional

Endfunction

Pleasesendusyourcommentaboutthispage

Page 145: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>DesigningReactorsfortheGardenPath>

AttachingtheReactors

Thenextstepinplanningareactor-basedapplicationistodeterminehowandwhentoattachreactors.Youneedtoattachtwoobjectreactorsforthepolylineborderofanygardenpath(onetorespondtoamodificationevent,theothertorespondtoerasure),andoneeditorreactortoalertyourapplicationwhenuserscompletetheirmodificationtothepolyline.Objectreactorsareattachedtoentities,whileeditorreactorsareregisteredwithAutoCAD.

Thereisanotherconsiderationtoaccountfor.Torecalculatethepolylineoutline—returnittoarectilinearshape—aftertheusermodifiesit,youmustknowwhatthevertexconfigurationwasbeforethemodification.Thisinformationcannotbedeterminedoncethepolylinehasbeenmodified.Bythattimeyoucanonlyretrieveinformationonwhatthenewconfigurationis.Sohowdoyousolvethis?Youcouldkeepthisinformationinaglobalvariable,butthereisamajorproblemwiththatidea.Userscandrawasmanygardenpathsastheywant,andeverynewpathwouldrequireanewglobalvariable.

Pleasesendusyourcommentaboutthispage

Page 146: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>DesigningReactorsfortheGardenPath>

StoringDatawithaReactor

YoucansolvetheproblemofsavingtheoriginalconfigurationbytakingadvantageofanotherfeatureofVLISPreactors—theabilitytostoredatawithinareactor.Whentheuserfirstdrawsapathboundary,youattachareactortotheboundary,alongwiththedatayouneedtosave.Thisentailsmodifyingyourmainprogramfunction,C:GPath,asfollows:

DefunC:GPath

Doeverythingthatisalreadydoneinthegardenpath

(anddon'tbreakanything)

Attachanobjectreactortothepolylineusingtheseparameters:

Apointertothepolylinejustdrawn,

Alistofdatathatyouwantthereactortorecord,

Alistofthespecificpolylineobjecteventstobetracked,

alongwiththeLISPcallbackfunctionstobeinvoked

Endoftheobjectreactorsetup

Attacheditorreactortothedrawingeditorusingthe

followingparameters:

Anydatayouwantattachedtothereactor(inthiscase,none)

Alistofthespecificeditorreactoreventstobetracked,

alongwiththeLISPcallbackfunctionstobeinvoked

Endoftheeditorreactorsetup

Endfunction

Pleasesendusyourcommentaboutthispage

Page 147: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>DesigningReactorsfortheGardenPath>

UpdatingtheC:GPathFunction

UpdatetheC:GPathfunctionbyaddingreactorcreationlogic.

ToaddreactorcreationlogictoC:GPath

1. Replaceyourversionofgpmain.lspwiththeupdatedversionshownbelow.Copythiscodefromthe<AutoCADdirectory>\Tutorial\VisualLISP\Lesson6directory:

(defunC:GPath(/

gp_PathData

gp_dialogResults

PolylineName

tileList

)

(setvar"OSMODE"0);;Turnoffobjectsnaps

;|

;;Lesson6addsastubbed-outcommandreactortoAutoCAD

;;However,itwouldbeundesirabletoreacttoevery

;;drawingofacircleshouldtheCOMMANDtilecreation

;;methodbechosenbytheuser.So,disablethe

;;*commandReactor*incaseitexists.

|;

(if*commandReactor*

(progn

(setq*commandReactor*nil)

(vlr-remove-all:VLR-Command-Reactor)

)

)

;;Asktheuserforinput:firstforpathlocationand

;;direction,thenforpathparameters.Continueonlyifyou

;;havevalidinput.Storethedataingp_PathData.

(if(setqgp_PathData(gp:getPointInput))

(if(setqgp_dialogResults

(gp:getDialogInput

(cdr(assoc40gp_PathData))

);_endofgp:getDialogInput

Page 148: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

);_endofsetq

(progn

;;Nowtaketheresultsofgp:getPointInputandappendthisto

;;theaddedinformationsuppliedbygp:getDialogInput

(setqgp_PathData(appendgp_PathDatagp_DialogResults))

;;Atthispoint,youhavealltheinputfromtheuser

;;Drawtheoutline,storingtheresultingpolyline"pointer"

;;inthevariablecalledPolylineName

(setqPolylineName(gp:drawOutlinegp_PathData))

;;Next,itistimetodrawthetileswithintheboundary.

;;Thegp_tileListcontainsalistoftheobjectpointersfor

;;thetiles.Bycountingupthenumberofpoints(usingthe

;;lengthfunction),wecanprintouttheresultsofhowmany

;;tilesweredrawn.

(princ"\nThepathrequired")

(princ

(length

(setqtileList(gp:Calculate-and-Draw-Tilesgp_PathData))

);_endoflength

);_endofprinc

(princ"tiles.")

;;Addthelistofpointerstothetiles(returnedby

;;gp:Calculate-and-Draw-Tiles)togp_PathData.Thiswill

;;bestoredinthereactordataforthereactorattached

;;totheboundarypolyline.Withthisdata,thepolyline

;;"knows"whattiles(circles)belongtoit.

(setqgp_PathData

(append(list(cons100tileList))

;allthetiles

gp_PathData

);_endofappend

);_endofsetq

;;Beforeweattachreactordatatoanobject,let'slookat

;;thefunctionvlr-object-reactor

;;vlr-object-reactorhasthefollowingarguments:

;;(vlr-object-reactorowner'sdatacallbacks)

;;ThecallbacksArgumentisalistcomprised

;;'(event_name.callback_function)

;;

;;Forthisexercisewewilluseallarguments

;;associatedwithvlr-object-reactor

;;Thesereactorfunctionswillexecuteonlyif

;;thepolylineinPolylineNameismodifiedorerased

(vlr-object-reactor

;;Thefirstargumentforvlr-object-reactoris

;;the"Owner'sList"argument.Thisiswhereto

;;placetheobjecttobeassociatedwiththe

;;reactor.Inthiscase,itisthevlaObject

;;storedinPolylineName.

(listPolylineName)

Page 149: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

;;Thesecondargumentcontainsthedataforthepath

gp_PathData

;;Thethirdargumentisthelistofspecificreactor

;;typesthatweareinterestedinusing

'

(

;;reactorthatiscalleduponmodificationoftheobject

(:vlr-modified.gp:outline-changed)

;;reactorthatiscalleduponerasureoftheobject

(:vlr-erased.gp:outline-erased)

)

);_endofvlr-object-reactor

;;Next,registeracommandreactortoadjustthepolyline

;;whenthechangingcommandisfinished

(if(not*commandReactor*)

(setq*commandReactor*

(VLR-Command-Reactor

nil;Nodataisassociatedwiththecommandreactor

'(

(:vlr-commandWillStart.gp:command-will-start)

(:vlr-commandEnded.gp:command-ended)

)

);_endofvlr-command-reactor

)

)

;;Thefollowingcoderemovesallreactorswhenthedrawingis

;;closed.Thisisextremelyimportant!!!!!!!!!

;;Withoutthisnotification,AutoCADmaycrashuponexiting!

(if(not*DrawingReactor*)

(setq*DrawingReactor*

(VLR-DWG-Reactor

nil;Nodataisassociatedwiththedrawingreactor

'((:vlr-beginClose.gp:clean-all-reactors)

)

);_endofvlr-DWG-reactor

)

)

);_endofprogn

(princ"\nFunctioncancelled.")

);_endofif

(princ"\nIncompleteinformationtodrawaboundary.")

);_endofif

(princ);exitquietly

);_endofdefun

;;;Displayamessagetolettheuserknowthecommandname.

(princ"\nTypeGPATHtodrawagardenpath.")

(princ)

2. Reviewthecodemodificationsandcommentsdescribingwhateachnew

Page 150: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

statementdoes.Thistutorialshowsallmodifiedcodeinboldface.

Pleasesendusyourcommentaboutthispage

Page 151: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>DesigningReactorsfortheGardenPath>

AddingReactorCallbackFunctions

Thereactorcallbackfunctionsaddasubstantialamountofcodetoyourapplication.ThiscodeisprovidedforyouintheLesson6directory.

Toaddthereactorcallbackfunctionstoyourprogram

1. Copythegpreact.lspfilefromtheTutorial\VisualLISP\Lesson6directorytoyourMyPathworkingdirectory.

2. OpentheGPathproject(ifitisnotalreadyopen),andchoosetheProjectPropertiesbuttoninthegpathprojectwindow.

3. Addthegpreact.lspfiletoyourproject.

4. Thegpreact.lspfilecanresideanywhereintheorderoffilesbetweenutils.lsp,whichmustremainfirst,andgpmain.lsp,whichshouldremainasthelastfile.Moveanyfiles,ifnecessary,thenchooseOK.

5. Openthegpreact.lspfilebydouble-clickingonthefilenamewithinthegpathprojectwindow.

Readthroughthecommentsinthefiletohelpyouunderstandwhatitisdoing.Notethatallthecallbackfunctionsarestubbedout;theonlyfunctionalitytheyperformistodisplayalertmessageswhentheyarefired.

Thelastfunctioninthefileissoimportantitdeservesaheadingofitsown.

Pleasesendusyourcommentaboutthispage

Page 152: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>DesigningReactorsfortheGardenPath>

CleaningUpAfterYourReactors

Reactorsareindeedveryactive.Whenyoudesignanapplicationthatreliesonthem,youcouldverywellspendagreatdealoftimecrashingyourprogramandpossiblycrashingAutoCADaswell.Ithelpstohaveatoolavailabletoremoveallthereactorsyouhaveadded,ifnecessary.

Thegpreact.lspfileincludesafunctiongp:clean-all-reactorsthatdoesn'tdomuchonitsown.Instead,itmakesacalltotheCleanReactorsfunction.Addthisfunctiontoyourutils.lspfilebycopyingthefollowingcodetotheendofthefile:

;;;--------------------------------------------------------------;

;;;Function:CleanReactors;

;;;--------------------------------------------------------------;

;;;Description:Generalutilityfunctionusedforcleaningup;

;;;reactors.Itcanbeusedduringdebugging,as;

;;;wellascleaningupanyopenreactorsbefore;

;;;adrawingisclosed.;

;;;--------------------------------------------------------------;

(defunCleanReactors()

(mapcar'vlr-remove-all

'(:VLR-AcDb-reactor

:VLR-Editor-reactor

:VLR-Linker-reactor

:VLR-Object-reactor

)

)

)

Pleasesendusyourcommentaboutthispage

Page 153: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>

TestDrivingYourReactors

Bynow,youshouldhaveallthenecessarypiecesinplacetousesomelivereactors.

Totestthereactorcode

1. Loadallthesourcecodefromyourproject.(ChoosetheLoadSourceFilesbuttoninthegpathprojectwindow.)

2. StarttheC:GPathfunction.Theprogramwilldrawagardenpathforyou,justasyouwereabletoinLesson5.Youwon'tseeanythinginterestingatfirst.

3. Trythefollowingactionsafteryoudrawthepath:

Moveapolylinevertex.Pickthepolylineandturnonitsgrips,thendragavertextoanewlocation.

Stretchthepolyline.

Movethepolyline.

Erasethepolyline.

Examinethemessagesthatappear.Youarewatchingthebehind-the-scenesactivitiesofapowerfulcapability.

(Ifyourapplicationisnotworkingcorrectlyandyoudonotwanttotakethetimetodebugitrightnow,youcanrunthesamplecodeprovidedintheTutorial\VisualLISP\Lesson6directory.UsetheGpath6projectinthatdirectory.)

Note Becauseofthereactorbehavior,youmaynoticethataftertestingareactorsequenceinAutoCAD,youcannotreturntoVLISPbypressingALT+TAB,or

Page 154: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

byclickingtoactivatetheVLISPwindow.Ifthishappens,simplyentervlispattheAutoCADCommandprompttoreturntoVLISP.

Topicsinthissection

ExaminingReactorBehaviorinDetail

Pleasesendusyourcommentaboutthispage

Page 155: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>TestDrivingYourReactors>

ExaminingReactorBehaviorinDetail

Withastackofscrappaper,starttracingthereactoreventswithintheapplication.Hereisanexampleofthekindsofthingsyoushouldtrack:

Drawtengardenpaths,thentrackthefollowingCommand/Objectcombinations,selectingthepolylinesinsuccession:

Erase/Polylineborder(path1)

Erase/Circlewithinapolyline(path2)

Erase/Twopolylines(paths3and4)

Move/Polylineborder(path5)

Move/Circlewithinapolyline(path6)

Move/Twopolylinesandseveralcircles(paths7and8)

MoveVertex(throughgrips)/Polylineborder(path9)

Stretch/Polylineborder(path10)

Thisexercisewillgiveyouagoodunderstandingofwhatishappeningbehindthescenes.AtanytimethroughoutLesson7whenthereactorfunctionality

Page 156: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

becomesconfusing,refertoyour“reactor-tracesheets.”

Pleasesendusyourcommentaboutthispage

Page 157: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ActingwithReactors>

WrappingUpLesson6

Inthislesson,youwereintroducedtoAutoCADreactorsandhowtoimplementthemusingVLISP.Youdesignedaplanforaddingreactorstothegardenpathapplication,andaddedsomeofthecodeyourprogramwillneedtoimplementtheplan.

Reactorscanaddagreatdealoffunctionalitytoanapplication,butremember—themorepowerfulyourprogramscanbe,thehardertheycancrash.

Anotherthingtokeepinmindisthatthewayyourapplicationisdesigned,thereactorfunctionalityisnotpersistentfromonedrawingsessiontothenext.Ifyousaveadrawingthatcontainsagardenpathhookeduptoreactors,thereactorswillnotbetherethenexttimeyouopenthedrawing.Youcanlearnaboutaddingpersistentreactorsbyreviewingthe“TransientversusPersistentReactors”topicintheAutoLISPDeveloper'sGuide,andthenreadingaboutthereferencedfunctionsintheAutoLISPReference.

Pleasesendusyourcommentaboutthispage

Page 158: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether

InLesson6,youlearnedthebasicmechanicsbehindreactor-basedapplications.InLesson7,youwilladdfunctionalitytothisknowledgeandcreateagardenpaththatknowshowandwhentomodifyitself.Aftertestingyourapplicationanddeterminingthatitworkssatisfactorily,youwillcreateaVisualLISP®applicationfromyourVLISPproject.

Youshouldconsiderthispartofthetutorialastheadvancedtopicssection.Ifyouareabeginner,youmaynotunderstandalltheAutoLISP®codepresentedhere.ThereareseveralAutoLISPbookslistedattheendofthislessonthatprovidemorethoroughinformationonsomeoftheadvancedAutoLISPconceptspresentedhere.

Topicsinthissection

PlanningtheOverallReactorProcessAddingtheNewReactorFunctionalityRedefiningthePolylineBoundaryWrappingUptheCodeBuildinganApplicationWrappingUptheTutorialLISPandAutoLISPBooks

Pleasesendusyourcommentaboutthispage

Page 159: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>

PlanningtheOverallReactorProcess

Youneedtodefineseveralnewfunctionsinthislesson.Ratherthanpresentyouwithdetailsonallaspectsofthenewcode,thislessonpresentsanoverviewandpointsouttheconceptsbehindthecode.Attheendofthelesson,youwillhaveallthesourcecodenecessarytocreateagardenpathapplicationidenticaltothesampleprogramyouraninLesson1.

Note Whenyouareinthemidstofdevelopinganddebuggingreactor-basedapplications,thereisalwaysthepotentialofleavingAutoCAD®inanunstablestate.Thiscanbecausedbyseveralsituations,suchasfailingtoremoveareactorfromdeletedentities.Forthisreason,itisrecommendedthatbeforebeginningLesson7,youshouldcloseVLISP,saveanyopenfilesasyoudoso,exitAutoCAD,thenrestartbothapplications.

BeginbyloadingtheprojectasitexistedattheendofLesson6.

Twoobviouspiecesofworkremaintobedoneinthegardenpathapplication:

Writingtheobjectreactorcallbacks.

Writingtheeditorreactorcallbacks.

Youalsoneedtoconsiderhowtohandletheglobalvariablesinyourprogram.Often,itisdesirabletohaveglobalsretainavaluethroughoutanAutoCADdrawingsession.Inthecaseofreactors,however,thisisnotthecase.Toillustratethis,imagineauserofyourgardenpathapplicationhasdrawnseveralgardenpathsinasingledrawing.Afterdoingthis,theusererasesthem,firstoneatatime,thentwoatatime,andsoon,untilallbutonepathiserased.

Lesson5introducedaglobalvariable*reactorsToRemove*,responsibleforstoringpointerstothereactorsforthepolylinesabouttobeerased.When*reactorsToRemove*isdeclaredingp:outline-erased,theeventletsyouknowthepolylineisabouttobeerased.Thepolylineisnotactuallyremoveduntilthegp:command-endedeventfires.

Page 160: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Thefirsttimetheuserdeletesapolyline,thingsworkjustasyouwouldexpect.Ingp:outline-erased,youstoreapointertothereactor.Whengp:command-endedfires,youremovethetilesassociatedwiththepolylinetowhichthereactorisattached,andalliswell.Then,theuserdecidestoerasetwopaths.Asaresult,yourapplicationwillgettwocallstogp:outline-erased,oneforeachpolylineabouttobeerased.Therearetwopotentialproblemsyoumustanticipate:

Whenyousetqthe*reactorsToRemove*variable,youmustaddapointertoareactortotheglobal,makingsurenottooverwriteanyvaluesalreadystoredthere.Thismeans*reactorsToRemove*mustbealiststructure,soyoucanappendreactorpointerstoit.Youcanthenaccumulateseveralreactorpointerscorrespondingtothenumberofpathstheuseriserasingwithinasingleerasecommand.

Everytimegp:command-will-startfires,indicatinganewcommandsequenceisbeginning,youshouldreinitializethe*reactorsToRemove*variabletonil.Thisisnecessarysothattheglobalisnotstoringreactorpointersfromthepreviouserasecommand.Ifyoudonotreinitializetheglobalvariableorusethecorrectdatastructure(inthiscase,alist),youwillgetunexpectedbehavior.Inthecaseofreactors,unexpectedbehaviorcanbefataltoyourAutoCADsession.

Hereisthechainofeventsthatneedstooccurforuserstoerasetwogardenpathswithasingleerasecommand.Notehowglobalvariablesarehandled:

Initiatetheerasecommand.Thistriggersthegp:command-will-startfunction.Set*reactorsToRemove*tonil.

Selecttwopolylines;yourapplicationisnotyetnotified.

PressENTERtoerasethetwoselectedpolylines.Yourapplicationgetsacallbacktogp:outline-erasedforoneofthepolylines.Additsreactorpointertothenullglobal,*reactorsToRemove*.Yourapplicationgetsacallbacktogp:outline-erasedforthesecondofthepolylines.Appenditsreactorpointertothe*reactorsToRemove*globalthatalreadycontainsthefirstreactor

Page 161: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

pointer.

AutoCADdeletesthepolylines.

Yourcallbackfunctiongp:command-endedfires.Eliminateanytilesassociatedwiththereactorpointersstoredin*reactorsToRemove*.

Inadditiontothe*reactorsToRemove*global,yourapplicationalsoincludesa*polyToChange*global,whichstoresapointertoanypolylinethatwillbemodified.Twoadditionalglobalsfortheapplicationwillbeintroducedlaterinthislesson.

Topicsinthissection

ReactingtoMoreUser-InvokedCommandsStoringInformationWithintheReactorObjects

Pleasesendusyourcommentaboutthispage

Page 162: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>PlanningtheOverallReactorProcess>

ReactingtoMoreUser-InvokedCommands

Whenwritingareactor-basedapplication,youneedtohandleanycommandthataffectsyourobjectsinasignificantway.OneofyourprogramdesignactivitiesshouldbetoreviewallpossibleAutoCADeditingcommandsanddeterminehowyourapplicationshouldrespondtoeachone.Theformatofthereactor-tracesheetshownneartheendofLesson6isverygoodforthispurpose.Invokethecommandsyouexpectyourusertouse,andwritedownthekindofbehaviorwithwhichyourapplicationshouldrespond.Otheractionstoplanforinclude

DeterminewhattodowhenusersissueUNDOandREDOcommands.

DeterminewhattodowhenusersissuetheOOPScommandaftererasingentitieslinkedwithreactors.

Topreventaverycomplexsubjectfrombecomingvery,verycomplex,thetutorialdoesnottrytocoverallthepossibilitiesthatshouldbecovered,andthefunctionalitywithinthislessoniskepttoanabsoluteminimum.

Eventhoughyouwon'tbebuildinginthecompletefunctionalityfortheseextracommands,examinewhatafewadditionaleditingfunctionswouldrequireyoutodo:

Ifusersstretchapolylineboundary(usingtheSTRETCHcommand)severalthingsshouldhappen.Itcouldbestretchedinanydirection,notjustonthemajororminoraxis,sotheboundarymayendupinaveryoddshape.Inaddition,youneedtotakeintoconsiderationhowmanyverticeshavebeenstretched.Asituationwhereonlyonevertexisstretchedwillresultinapolylinequitedifferentfromoneinwhichtwoverticesaremoved.Inanycase,thetilesmustbeerasedandnewpositionsrecalculatedonceyoudeterminetheadjustmentsneededtotheboundary.

Ifusersmoveapolylineboundary,allthetilesshouldbeerased,thenredrawninthenewlocation.Thisisafairlysimpleoperation,because

Page 163: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

thepolylineboundarydidnotchangeitssizeorshape.

Ifusersscaleapolylineboundary,youneedtomakeadecision.Shouldthetilesbescaledupaswell,sothatthepathcontainsthesamenumberoftiles?Or,shouldthetilesizeremainthesameandtheapplicationaddorremovetiles,dependingonwhetherthepolylinewasscaledupordown?

Ifusersrotateapolylineboundary,allthetilesshouldbeerased,thenredrawnintheneworientation.

Tobegin,though,justplanforthefollowing:

Warntheuseruponcommand-startthattheselectededitcommand(suchasstretch,move,orrotate)willhavedetrimentaleffectsonagardenpath.

Iftheuserproceeds,erasethetilesanddonotredrawthem.

Removethereactorsfromthepathoutline.

Note Inadditiontouser-invokedAutoCADcommands,entitiesmayalsobemodifiedordeletedthroughAutoLISPorObjectARX®applications.TheexampleprovidedintheGardenPathtutorialdoesnotcoverprogrammaticmanipulationofthegardenpathpolylineboundary,suchasthrough(entdel<polylineentity>).Inthiscase,theeditorreactorevents:vlr-commandWillStartand:vlr-commandEndedwillnotbetriggered.

Pleasesendusyourcommentaboutthispage

Page 164: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>PlanningtheOverallReactorProcess>

StoringInformationWithintheReactorObjects

Oneotherimportantaspectoftheapplicationyouneedtothinkaboutiswhatkindofinformationtoattachtotheobjectreactorthatiscreatedforeachpolylineentity.InLesson6,youaddedcodethatattachedthecontentsofgp_PathData(theassociationlist)tothereactor.Youexpandedthedatacarriedwithingp_PathDatabyaddinganewkeyedfield(100)totheassociationlist.Thisnewsublistisalistofpointerstoallthecircleentitiesassignedtoapolylineboundary.

Becauseoftheworkthatneedstobedonetorecalculatethepolylineboundary,fouradditionalkeyvaluesshouldbeaddedtogp_pathData:

;;;StartingPoint;

;;;(12.BottomStartingPoint)15------------------------14;

;;;(15.TopStartingPoint)||;

;;;EndingPoint10----pathAngle--->11;

;;;(13.BottomEndingPoint)||;

;;;(14.TopEndingPoint)12------------------------13;

;;;;

Theseorderedpointsarenecessarytorecalculatethepolylineboundarywhenevertheuserdragsacornergriptoanewlocation.Thisinformationalreadyexistswithinthegp:drawOutlinefunctioningpdraw.lsp.Butlookatthereturnvalueofthefunction.Currently,onlythepointertothepolylineobjectisreturned.Soyouneedtodothreethings:

Assembletheperimeterpointsintheformatrequired.

Modifythefunctionsothatitreturnstheperimeterpointlistsandthepointertothepolyline.

ModifytheC:GPathfunctionsothatitcorrectlydealswiththenewformatofthevaluesreturnedfromgp:drawOutline.

Assemblingtheperimeterpointlistsissimple.Lookatthecodein

Page 165: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

gp:drawOutline.Thelocalvariablep1correspondstothekeyvalue12,p2to13,p3to14,andp4to15.Youcanaddthefollowingfunctioncalltoassemblethisinformation:

(setqpolyPoints(list

(cons12p1)

(cons13p2)

(cons14p3)

(cons15p4)

))

Modifyingthefunctionsothatitreturnsthepolylineperimeterpointsandthepolylinepointerisalsoeasy.Asthelastexpressionwithingp:drawOutline,assemblealistofthetwoitemsofinformationyouwanttoreturn.

(listplinepolyPoints)

Toaddprogramlogictosavethepolylineperimeterpoints

1. Modifygp:drawOutlinebymakingthechangesshowninboldfaceinthefollowingcode(don'toverlooktheadditionofthepolyPointslocalvariabletothedefunstatement):

(defungp:drawOutline(BoundaryData/PathAngle

WidthHalfWidthStartPtPathLength

angm90angp90p1p2

p3p4poly2Dpoints

poly3DpointsplineStylepline

polyPoints

)

;;extractthevaluesfromthelistBoundaryData.

(setqPathAngle(cdr(assoc50BoundaryData))

Width(cdr(assoc40BoundaryData))

HalfWidth(/Width2.00)

StartPt(cdr(assoc10BoundaryData))

PathLength(cdr(assoc41BoundaryData))

angp90(+PathAngle(Degrees->Radians90))

angm90(-PathAngle(Degrees->Radians90))

p1(polarStartPtangm90HalfWidth)

p2(polarp1PathAnglePathLength)

p3(polarp2angp90Width)

p4(polarp3(+PathAngle

(Degrees->Radians180))PathLength)

poly2Dpoints(apply'append

(mapcar'3dPoint->2dPoint(listp1p2p3p4))

Page 166: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

)

poly3Dpoints(mapcar'float(appendp1p2p3p4))

;;getthepolylinestyle.

plineStyle(strcase(cdr(assoc4BoundaryData)))

;;AddpolylinetothemodelspaceusingActiveXautomation.

pline(if(=plineStyle"LIGHT")

;;createalightweightpolyline.

(vla-addLightweightPolyline

*ModelSpace*;GlobalDefinitionforModelSpace

(gp:list->variantArraypoly2Dpoints)

;dataconversion

);_endofvla-addLightweightPolyline

;;orcreatearegularpolyline.

(vla-addPolyline

*ModelSpace*

(gp:list->variantArraypoly3Dpoints)

;dataconversion

);_endofvla-addPolyline

);_endofif

polyPoints(list

(cons12p1)

(cons13p2)

(cons14p3)

(cons15p4)

)

);_endofsetq

(vla-put-closedplineT)

(listplinepolyPoints)

);_endofdefun

2. ModifytheC:GPathfunction(ingpmain.lsp).Lookforthelineofcodethatcurrentlylookslikethis:

(setqPolylineName(gp:drawOutlinegp_PathData))

Changeitsoitappearsasfollows:

(setqPolylineList(gp:drawOutlinegp_PathData)

PolylineName(carPolylineList)

gp_pathData(appendgp_pathData(cadrPolylineList))

);_endofsetq

Thegp_PathDatavariablenowcarriesalltheinformationrequiredbythereactorfunction.

3. AddPolylineListtothelocalvariablessectionoftheC:GPathfunctiondefinition.

Page 167: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Pleasesendusyourcommentaboutthispage

Page 168: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>

AddingtheNewReactorFunctionality

InLesson6,youhookedupcallbackfunctiongp:command-will-starttothereactorevent:vlr-commandWillStart.Asitcurrentlyexists,thefunctiondisplayssomemessagesandinitializestwoglobalvariables,*polyToChange*and*reactorsToRemove*,tonil.

Toaddfunctionalitytothegp:command-will-startcallbackfunction

1. Openyourgpreact.lspfile.

2. Inthegp:command-will-startfunction,addtwovariablestothesetqfunctioncallbymodifyingitasfollows:

;;Resetallfourreactorglobalstonil.

(setq*lostAssociativity*nil

*polyToChange*nil

*reactorsToChange*nil

*reactorsToRemove*nil)

3. Replacetheremainingcodeingp:command-will-start,uptothelastprincfunctioncall,withthefollowingcode:

(if(member(setqcurrentCommandName(carcommand-list))

'("U""UNDO""STRETCH""MOVE"

"ROTATE""SCALE""BREAK""GRIP_MOVE"

"GRIP_ROTATE""GRIP_SCALE""GRIP_MIRROR")

);_endofmember

(progn

(setq*lostAssociativity*T)

(princ"\nNOTE:The")

(princcurrentCommandName)

(princ"commandwillbreakapath'sassociativity.")

);_endofprogn

);_endofif

Thiscodecheckstoseeiftheuserissuedacommandthatbreaksthe

Page 169: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

associativitybetweenthetilesandthepath.Iftheuserissuedsuchacommand,theprogramsetsthe*lostAssociativity*globalvariableandwarnstheuser.Asyouexperimentwiththegardenpathapplication,youmaydiscoveradditionaleditingcommandsthatcanmodifythegardenpathandcausethelossofassociativity.Addthesecommandstothequotedlistsothattheuserisawareofwhatwillhappen.Whenthisfunctionfires,theuserhasstartedacommandbuthasnotselectedanyentitiestomodify.Theusercouldstillcancelthecommand,leavingthingsunchanged.

Topicsinthissection

AddingActivitytotheObjectReactorCallbackFunctionsDesigningthegp:command-endedCallbackFunctionHandlingMultipleEntityTypesUsingActiveXMethodsinReactorCallbackFunctionsHandlingNonlinearReactorSequencesCodingthecommand-endedFunctionUpdatinggp:Calculate-and-Draw-TilesModifyingOtherCallstogp:Calculate-and-Draw-Tiles

Pleasesendusyourcommentaboutthispage

Page 170: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>AddingtheNewReactorFunctionality>

AddingActivitytotheObjectReactorCallbackFunctions

InLesson6,youregisteredtwocallbackfunctionswithobjectreactorevents.Thegp:outline-erasedfunctionwasassociatedwiththe:vlr-erasedreactorevent,andgp:outline-changedwasassociatedwiththe:vlr-modifiedevent.Youneedtomakethesefunctionsdowhattheyareintendedtodo.

Tomaketheobjectreactorcallbackfunctionsdowhattheyareintendedtodo

1. Ingpreact.lsp,changegp:outline-erasedsoitappearsasfollows:

(defungp:outline-erased(outlinePolyreactorparameterList)

(setq*reactorsToRemove*

(consreactor*reactorsToRemove*))

(princ)

);_endofdefun

Thereisjustoneoperationperformedhere.Thereactorattachedtothepolylineissavedtoalistofallreactorsthatneedtoberemoved.(Remember:thoughreactorsareattachedtoentities,theyareseparateobjectsentirely,andtheirrelationshipstoentitiesneedtobemanagedjustascarefullyasregularAutoCADentities.)

2. Changegp:outline-changedtoreflectthefollowingcode:

(defungp:outline-changed(outlinePolyreactorparameterList)

(if*lostAssociativity*

(setq*reactorsToRemove*

(consreactor*reactorsToRemove*))

(setq*polytochange*outlinePoly

*reactorsToChange*(consreactor*reactorsToChange*))

)

(princ)

)

Page 171: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Therearetwocategoriesoffunctionsthatcanmodifythepolylineoutline.Thefirstcategorycontainsthosecommandsthatwillbreakthepath'sassociativitywithitstiles.Youcheckedforthisconditioningp:command-will-startandsetthe*lostAssociativity*globalvariableaccordingly.Inthiscase,thetilesneedtobeerased,andthepathisthenintheuser'shands.TheothercategoryisthegripmodeoftheSTRETCHcommand,whereassociativityisretainedandyouneedtostraightenouttheoutlineaftertheuserhasfinisheddraggingavertextoanewlocation.The*polyToChange*variablestoresaVLA-Objectpointertothepolylineitself.Thiswillbeusedinthegp:command-endedfunctionwhenitcomestimetorecalculatethepolylineborder.

Pleasesendusyourcommentaboutthispage

Page 172: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>AddingtheNewReactorFunctionality>

Designingthegp:command-endedCallbackFunction

Thegp:command-endededitorreactorcallbackfunctioniswheremostactiontakesplace.Untilthisfunctioniscalled,thegardenpathborderpolylinesare“openformodify;”thatis,usersmaystillbemanipulatingthebordersinAutoCAD.Withinthereactorsequence,youhavetowaituntilAutoCADhasdoneitspartoftheworkbeforeyouarefreetodowhatyouwanttodo.

Thefollowingpseudo-codeillustratesthelogicofthegp:command-endedfunction:

Determinetheconditionofthepolyline.

CONDITION1-POLYLINEERASED(Erasecommand)

Erasethetiles.

CONDITION2-LOSTASSOCIATIVITY(Move,Rotate,etc.)

Erasethetiles.

CONDITION3-GRIP_STRETCH-REDRAWANDRE-TILE

Erasethetiles.

Getthecurrentboundarydatafromthepolyline.

Ifitisalightweightpolyline,

Processboundarydataas2D

Else

Processboundarydataas3D

Endif

Redefinethepolylineborder(passinparametersofthecurrent

boundaryconfiguration,aswellastheold).

Getthenewboundaryinformationandputitintotheformat

requiredforsettingbackintothepolylineentity.

Regeneratethepolyline.

Redrawthetiles(forceActiveXdrawing).

Puttherevisedboundaryinformationbackintothereactor

namedin*reactorsToChange*.

Endfunction

Thepseudo-codeisrelativelystraightforward,butthereareseveralimportantdetailsburiedinthepseudo-code,andtheyarethingsyouwouldnotbeexpectedtoknowatthispoint.

Page 173: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Pleasesendusyourcommentaboutthispage

Page 174: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>AddingtheNewReactorFunctionality>

HandlingMultipleEntityTypes

Thefirstdetailisthatyourapplicationmaydrawtwokindsofpolylines:old-styleandlightweight.Thesedifferentpolylinetypesreturntheirentitydataindifferentformats.Theold-stylepolylinereturnsalistoftwelvereals:foursetsofX,Y,andZpoints.Thelightweightpolyline,though,returnsalisteightreals:foursetsofXandYpoints.

Youneedtodosomecalculationstodeterminetherevisedpolylineboundaryafterausermovesoneofthevertices.Itwillbealoteasiertodothecalculationsifthepolylinedatahasaconsistentformat.

TheLesson7versionoftheutils.lspfilecontainsfunctionstoperformthenecessaryformatconversions:xyzList->ListOfPointsextractsandformats3Dpointlistsintoalistoflists,andxyList->ListOfPointsextractsandformats2Dpointlistsintoalistoflists.

Toaddthecodeforconvertingpolylinedataintoaconsistentformat

1. Ifyouhaveacopyofutils.lspopeninaVLISPtexteditorwindow,closeit.

2. Copytheversionofutils.lspfromtheTutorial\VisualLISP\Lesson7directoryintoyourworkingdirectory.Inadditiontothetwofunctionsthatreformatpolylinedata,utils.lspcontainsadditionalutilityfunctionsneededinhandlinguseralterationstothegardenpath.

3. Openutils.lspinaVLISPtexteditorwindowandreviewthenewcode.

Pleasesendusyourcommentaboutthispage

Page 175: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>AddingtheNewReactorFunctionality>

UsingActiveXMethodsinReactorCallbackFunctions

Theseconddetailappearinginthepseudo-codeshowsupneartheend,atthestepforredrawingthetiles.Hereisthepseudo-codestatement:

Redrawthetiles(forceActiveXdrawing)

Theparentheticalphrasesaysitall:forceActiveXdrawing.Whyisthisrequired?Whycan'ttheapplicationusetheobjectcreationpreferencestoredintheassociationsublist?

Theanswerisyoucannotusethecommandfunctionforentitycreationwithinareactorcallbackfunction.ThishastodowithsomeinternalworkingsofAutoCAD.YouneedtoforcethetiledrawingroutinetouseActiveX.Youwillhearmoreaboutthisissuelaterinthislesson.

Pleasesendusyourcommentaboutthispage

Page 176: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>AddingtheNewReactorFunctionality>

HandlingNonlinearReactorSequences

Thefinalimportantdetaildealswithaquirkinthecommand/reactorsequenceinAutoCADwhenusersmodifyapolylinebyusingthespecializedGRIPcommands.Thesecommands,suchasGRIP_MOVEandGRIP_ROTATE,areavailablefromashortcutmenuafteryouselectthegripofanobjectandright-click.ThereactorsequenceisnotaslinearasasimpleMOVEorERASEcommand.Ineffect,theuserischangingtoadifferentcommandwhileinthemidstofanother.Todemonstratethissituation,youcanloadthecodefromLesson6thattracesthesequenceofreactorevents.OrsimplyreviewthefollowingannotatedVLISPConsolewindowoutputtoseewhathappens:

;;Tostart,selectthepolylineandsomeofthecirclesbyusinga

;;crossingselectionbox.Theitemsintheselectionset--

;;thechosencirclesandthepolyline--arenowshownwithgripson.

;;Toinitiatethesequence,clickononeofthepolylinegrips:

(GP:COMMAND-WILL-START#<VLR-Command-reactor>(GRIP_STRETCH))

;;Nowchangethecommandtoamovebyright-clickingandchoosing

;;MOVEfromthepop-upmenu.Noticethatthecommand-ended

;;reactorfiresinordertocloseouttheGRIP_STRETCHcommand

;;withouthavingfiredanobjectreactorevent:

(GP:COMMAND-ENDED#<VLR-Command-reactor>(GRIP_STRETCH))

(GP:COMMAND-WILL-START#<VLR-Command-reactor>(GRIP_MOVE))

;;Nowdragtheoutline(andtheselectedcircles)toanewlocation.

(GP:OUTLINE-CHANGED#<VLA-OBJECTIAcadLWPolyline028f3188>

#<VLR-Object-reactor>nil)

(GP:COMMAND-ENDED#<VLR-Command-reactor>(GRIP_MOVE))

Thisdemonstratesthatyoucannotbecertainyourobjectreactorcallbackswillbecalledinallcases.

Thereisarelatedquirkinthissequence.Evenduringthefinalcommand-endedcallback,thecirclesthatarestillpartofthegripselectionsetcannotbedeleted.ThesecirclesarestillopenbyAutoCAD.Ifyouattempttoerasethemduringthecommand-endedcallback,youcancrashAutoCAD.Togetaroundthis,youcanuseanotherglobalvariabletostorealistofpointerstothetileobjectsuntilthey

Page 177: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

canbedeleted.

Toprocessnonlinearreactorsequences

1. Addthefollowingfunctiontothegpreact.lspfile:

(defungp:erase-tiles(reactor/reactorDatatilestile)

(if(setqreactorData(vlr-datareactor))

(progn

;;Tilesinthepatharestoredasdatainthereactor.

(setqtiles(cdr(assoc100reactorData)))

;;Erasealltheexistingtilesinthepath.

(foreachtiletiles

(if(and(null(membertile*Safe-to-Delete*))

(not(vlax-erased-ptile))

)

(progn

(vla-put-visibletile0)

(setq*Safe-to-Delete*(constile*Safe-to-Delete*))

)

)

)

(vlr-data-setreactornil)

)

)

)

Thisnewfunctionwillbeusedinthefirstphaseoferasingtiles.Noticethatthetilesarenotactuallyerased:theyaremadeinvisibleandareaddedtoaglobalvariablenamed*Safe-to-Delete*.

2. Addthefollowingfunctiontothegpreact.lspfile:

(defunGp:Safe-Delete(activeCommand)

(if(not(equal

(strcase(substractiveCommand15))

"GRIP_"

)

)

(progn

(if*Safe-to-Delete*

(foreachItem*Safe-to-Delete*

(if(not(vlax-erased-pItem))

(vla-eraseitem)

)

)

)

Page 178: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

(setq*Safe-to-Delete*nil)

)

)

)

ThisfunctioncanbeinvokedatatimewhenaGRIP_MOVEorGRIP_STRETCHcommandisnotbeingexecuted.

Pleasesendusyourcommentaboutthispage

Page 179: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>AddingtheNewReactorFunctionality>

Codingthecommand-endedFunction

Nowthatyouhaveseenthepseudo-codeandhandledsomeimportantdetails,replacethestubbed-outcodeinthegp:command-endedreactorcallbackwiththefollowing:

(defungp:command-ended(reactorcommand-list

/objReactor

reactorToChangereactorData

coordinateValuescurrentPoints

newReactorDatanewPts

tileList

)

(cond

;;CONDITION1-POLYLINEERASED(Erasecommand)

;;Ifoneormorepolylinebordersarebeingerased(indicated

;;bythepresenceof*reactorsToRemove*),erasethetiles

;;withintheborder,thenremovethereactor.

(*reactorsToRemove*

(foreachobjReactor*reactorsToRemove*

(gp:erase-tilesobjReactor)

)

(setq*reactorsToRemove*nil)

)

;;CONDITION2-LOSTASSOCIATIVITY(Move,Rotate,etc.)

;;Ifassociativityhasbeenlost(undo,move,etc.),then

;;erasethetileswithineachborder

;;

((and*lostassociativity**reactorsToChange*)

(foreachreactorToChange*reactorsToChange*

(gp:erase-tilesreactorToChange)

)

(setq*reactorsToChange*nil)

)

;;CONDITION3-GRIP_STRETCH

;;Inthiscase,theassociativityofthetilestothepathis

;;kept,butthepathandthetileswillneedtobe

;;recalculatedandredrawn.AGRIP_STRETCHcanonlybe

;;performedonasinglePOLYLINEatatime.

Page 180: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

((and(not*lostassociativity*)

*polytochange*

*reactorsToChange*

(member"GRIP_STRETCH"command-list)

;;foraGRIP_STRETCH,therewillbeonlyonereactorin

;;theglobal*reactorsToChange*.

(setqreactorData

(vlr-data(setqreactorToChange

(car*reactorsToChange*)

)

)

)

)

;;First,erasethetileswithinthepolylineborder.

(gp:erase-tilesreactorToChange)

;;Next,getthecurrentcoordinatevaluesofthepolyline

;;vertices.

(setqcoordinateValues

(vlax-safearray->list

(vlax-variant-value

(vla-get-coordinates*polyToChange*)

)

)

)

;;Iftheoutlineisalightweightpolyline,youhave

;;2dpoints,souseutilityfunctionxyList->ListOfPoints

;;toconvertthecoordinatedataintolistsof

;;((xy)(xy)...)points.Otherwise,usethe

;;xyzList->ListOfPointsfunctionthatdeals

;;with3dpoints,andconvertsthecoordinatedatainto

;;listsof((xyz)(xyz)...)points.

(setqCurrentPoints

(if(=(vla-get-ObjectName*polytochange*)"AcDbPolyline")

(xyList->ListOfPointscoordinateValues)

(xyzList->ListOfPointscoordinateValues)

)

)

;;SendthisnewinformationtoRedefinePolyBorder--this

;;willreturnthenewPolylineBorder

(setqNewReactorData

(gp:RedefinePolyBorderCurrentPointsreactorData)

)

;;GetalltheborderPointsand...

(setqnewpts(list(cdr(assoc12NewReactorData))

(cdr(assoc13NewReactorData))

(cdr(assoc14NewReactorData))

(cdr(assoc15NewReactorData))

)

)

;;...updatetheoutlineofthepolylinewiththenewpoints

Page 181: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

;;calculatedabove.Ifdealingwithalightweightpolyline,

;;convertthesepointsto2D(sinceallthepointsin

;;newptsare3D),otherwiseleavethemalone.

(if(=(cdr(assoc4NewReactorData))"LIGHT")

(setqnewpts(mapcar'(lambda(point)

(3dPoint->2dPointPoint)

)

newpts

)

)

)

;;Nowupdatethepolylinewiththecorrectpoints.

(vla-put-coordinates

*polytochange*

;;Fordescriptionofthelist->variantArrayseeutils.lsp.

(gp:list->variantArray(apply'appendnewpts))

)

;;NowusethecurrentdefinitionoftheNewReactorData,

;;whichisreallythesameasthegardenpathdata

;;structure.Theonlyexceptionisthatthefield(100)

;;containingthelistoftilesisnil.ThisisOKsince

;;gp:Calculate-and-Draw-Tilesdoesnotrequirethisfield

;;todrawthetiles.Infactthisfunctioncreatesthetiles

;;andreturnsalistofdrawntiles.

(setqtileList(gp:Calculate-and-Draw-Tiles

;;pathdatalistwithoutcorrecttilelist

NewReactorData

;;Objectcreationfunction

;;Withinareactorthis*MUST*beActiveX

"ActiveX"

)

)

;;Nowthatyouhavereceivedallthetilesdrawn,rebuild

;;thedatastructurewiththecorrecttileListvalueand

;;resetthedatapropertyinthereactor.

;;Updatethetilesassociatedwiththepolylineborder.

(setqNewReactorData

(subst(cons100tileList)

(assoc100NewReactorData)

NewReactorData

)

)

;;Bynowyouhavethenewdataassociatedwiththepolyline.

;;Allthereislefttodoisassociateitwiththereactor

;;usingvlr-data-set.

(vlr-data-set(car*reactorsToChange*)NewReactorData)

;;Removeallreferencestothetemporary

;;variables*polytochange*and*reactorsToChange*.

(setq*polytochange*nil

*reactorsToChange*nil

Page 182: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

)

)

)

;;Deleteanyitemsinthe*Safe-to-Delete*globalifyoucan!!!

(Gp:Safe-Delete(carcommand-list))

(princ)

)

Pleasesendusyourcommentaboutthispage

Page 183: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>AddingtheNewReactorFunctionality>

Updatinggp:Calculate-and-Draw-Tiles

Earlierinthislesson,itwasnotedthatyouneedtoforcegp:Calculate-and-Draw-TilestouseActiveXtocreateobjectswheninvokedfromareactorcallback.Thismeansoverridingtheobjectcreationstyle(ActiveX,entmake,orcommand)chosenbytheuser,ifnecessary.Thecodeyoujustupdated,inthegp:command-endedfunction,containsthefollowinginvocationofthetiledrawingroutine:

(setqtileList(gp:Calculate-and-Draw-Tiles

;;pathdatalistwithoutcorrecttilelist.

NewReactorData

;;Objectcreationfunction.

;;Withinareactorthis*MUST*beActiveX.

"ActiveX"

)

)

Twoparametersarepassedtogp:Calculate-and-Draw-Tiles:NewReactorData(whichisalistintheformoftheoriginalgp_PathDataassociationlist)andthestring"ActiveX"(whichwillsettheobjectcreationstyle).Buttakealookatthecurrentdefinitionofgp:Calculate-and-Draw-Tiles.(Incaseyouhaveforgotten,thisfunctionisdefinedingpdraw.lsp.)Hereisthepartofthefunctionthatdeclarestheparametersandlocalvariables:

(defungp:Calculate-and-Draw-Tiles(BoundaryData/

PathLengthTileSpace

TileRadiusSpaceFilled

SpaceToFillRowSpacing

offsetFromCenterrowStartPoint

pathWidthpathAngle

ObjectCreationStyleTileList)

Noticeonlythatoneparameteriscurrentlyspecified,andObjectCreationStyleisidentifiedasalocalvariable.Reviewhowthe

Page 184: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

ObjectCreationStylevariableisset,whichisalittlefartherintothefunction:

(setqObjectCreationStyle(strcase(cdr(assoc3BoundaryData))))

TheObjectCreationStyleiscurrentlysetinternallywithinthefunctionbyretrievingthevaluetuckedawayintheBoundaryDatavariable(theassociationlist).Butnowyouneedtobeabletooverridethatvalue.

Tomodifygp:Calculate-and-Draw-Tilestoacceptanobjectcreationstyleargument

1. AddtheObjectCreationStylevariabletothefunctionargument.

2. RemoveObjectCreationStylefromthelocalvariables.Thedefunstatementforthefunctionshouldlooklikethefollowing:

(defungp:Calculate-and-Draw-Tiles(BoundaryData

ObjectCreationStyle

/PathLengthTileSpace

TileRadiusSpaceFilled

SpaceToFileRowSpacing

offsetFromCenterrowStartPoint

pathWidthpathAngle

TileList);removeObjectCreationStylefromlocals

Notethatifyoudeclareavariablebothasaparameter(beforetheslash)andasalocalvariable(aftertheslash),VLISPwillpointthisouttoyou.Forexample,ifyoudeclareObjectCreationStyleasbothaparameterandavariable,thenusetheVLISPsyntaxcheckingtoolonthegp:Calculate-and-Draw-Tilesfunction,thefollowingmessagewillappearintheBuildOutputwindow:

;***WARNING:samesymbolbeforeandafter/inargumentslist:OBJECTCREATIONSTYLE

3. Modifythefirstsetqexpressionwithingp:Calculate-and-Draw-Tilessothatitlookslikethefollowing:

(setq

PathLength(cdr(assoc41BoundaryData))

TileSpace(cdr(assoc43BoundaryData))

TileRadius(cdr(assoc42BoundaryData))

Page 185: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

SpaceToFill(-PathLengthTileRadius)

RowSpacing(*(+TileSpace(*TileRadius2.0))

(sin(Degrees->Radians60))

)

SpaceFilledRowSpacing

offsetFromCenter0.0

offsetDistance/(+(*TileRadius2.0)TileSpace)2.0)

rowStartPointcdr(assoc10BoundaryData))

pathWidthcdr(assoc40BoundaryData))

pathAnglecdr(assoc50BoundaryData))

);_endofsetq

(if(notObjectCreationStyle)

(setqObjectCreationStyle(strcase(cdr(assoc3BoundaryData))))

)

TheoriginalassignmentstatementforObjectCreationStylehasbeenremoved.ThecodenowcheckstoseeifavaluehasbeenprovidedforObjectCreationStyle.IfObjectCreationStyleisnotset(thatis,thevalueisnil),thefunctionassignsitavaluefromtheBoundaryDatavariable.Thereisonemoreseriesofchangesyouneedtomaketogp:Calculate-and-Draw-Tiles.

Pleasesendusyourcommentaboutthispage

Page 186: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>AddingtheNewReactorFunctionality>

ModifyingOtherCallstogp:Calculate-and-Draw-Tiles

Inthereactorcallback,ahard-codedstring"ActiveX"ispassedtogp:Calculate-and-Draw-TilesastheObjectCreationStyleargument.Butwhatabouttheothertimesgp:Calculate-and-Draw-Tilesisinvoked?

IfyourememberbacktoLesson4,itwaspointedoutthatwheneveryouchangeastubbed-outfunction,youneedtoaskthefollowingquestions:

Hasthefunctioncall(invocation)changed?Thatis,doesthefunctionstilltakethesamenumberofarguments?

Doesthefunctionreturnsomethingdifferent?

Thesamequestionsneedtobeaskedanytimeyoumakeasignificantchangetoaworkingfunctionasyoubuild,refine,andupdateyourapplications.Inthiscase,youneedtofindanyotherfunctionsinyourprojectthatinvokegp:Calculate-and-Draw-Tiles.VLISPhasafeaturethathelpsyoudothis.

Tofindallcallstogp:Calculate-and-Draw-Tilesinyourproject

1. IntheVLISPtexteditorwindow,double-clickonthewordgp:Calculate-and-Draw-Tileswithinthegpdraw.lspfile.

2. ChooseSearch FindfromtheVLISPmenu.

Becauseyoupreselectedthefunctionname,itisalreadylistedasthestringtosearchfor.

3. SelecttheProjectbuttonlistedunderSearchintheFinddialogbox.Whenyouselectthisoption,theFinddialogboxexpandsatthebottom,

Page 187: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

andyoucanselecttheprojecttobesearched.

4. Specifyyourcurrentprojectname,thenchoosetheFindbutton.VLISPdisplaystheresultsintheFindoutputwindow:

5. LookattheresultsintheFindOutputwindowanddeterminewhetherthereareanyotherlocationsinyourcodewhereyoumakeacalltogp:Calculate-and-Draw-Tiles.Thereshouldonlybeone:alocationwithingpmain.lsp.

6. IntheFindOutputwindow,double-clickonthelineofcodecallinggp:Calculate-and-Draw-Tiles.VLISPactivatesatexteditorwindowandtakesyourighttothatlineofcodeingpmain.lsp.Thecodecurrentlyappearsasfollows:

(setqtilelist(gp:Calculate-and-Draw-Tilesgp_PathData))

7. Replacethelineofcodewiththefollowing:

(setqtilelist(gp:Calculate-and-Draw-Tilesgp_PathDatanil))

Whynil?Takeanotherlookatthepseudo-code:

IfObjectCreationStyleisnil,assignitfromtheBoundaryData.

Passingnilasaparametertogp:Calculate-and-Draw-Tilescausesthatfunctiontochecktheuser'schoiceofhowtodrawthetiles(asdeterminedbythedialogboxselectionandstoredingp_PathData).Subsequentcallsfromthecommand-endedreactorcallback,however,willoverridethisbehaviorbyforcingtheuseofActiveX.

Congratulations!Younowhavethebasicreactorfunctionalityinplace.Ifyouprefer,copythegpmain.lspandgpdraw.lspfilesfromtheTutorial\VisualLISP\Lesson7intoyourworkingdirectoryandexaminethecompleted,debuggedcode.

Thereisstillalotofworktobedone,anditisalltriggeredfromthisfragmentofcodeinthegp:Command-endedfunction:

(setqNewReactorData

(gp:RedefinePolyBorderCurrentPointsreactorData)

Page 188: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

);_endofsetq

Pleasesendusyourcommentaboutthispage

Page 189: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>

RedefiningthePolylineBoundary

Youhaveworkedhardtogettothispoint,andyourbrainhasprobablyhadenoughnewconcepts,terms,commands,andimperativesforawhile.Withthatinmind,itisrecommendedthatyoucopythesamplecodesuppliedwiththetutorial,ratherthanenteringitonyourown.

Tocopythecodeusedtoredefinethepolylineboundary

1. Copythefilegppoly.lspfromtheTutorial\VisualLISP\Lesson7directoryintoyourworkingdirectory.

2. Intheprojectwindowforyourproject,choosetheProjectPropertiesbutton.

3. Addthegppoly.lspfiletotheproject.

4. ChooseOKtoaccepttheprojectwiththeadditionalfile.

5. Intheprojectwindow,double-clickthegppoly.lspfiletoopenit.

Topicsinthissection

LookingattheFunctionsingppoly.lspUnderstandingthegp:RedefinePolyBorderFunctionUnderstandingthegp:FindMovedPointFunctionUnderstandingthegp:FindPointInListFunctionUnderstandingthegp:recalcPolyCornersFunctionUnderstandingthegp:pointEqual,gp:rtos2,andgp:zeroSmallNumFunctions

Page 190: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Pleasesendusyourcommentaboutthispage

Page 191: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>RedefiningthePolylineBoundary>

LookingattheFunctionsingppoly.lsp

Thefilegppoly.lspcontainsanumberoffunctionsrequiredforstraighteningapolylinewhenasinglegriphasbeenstretched.Onlysomeofthesefunctionswillbeexplainedindepthinthistutorial.

Note ThissectionoftheGardenPathtutorialcontainssomeofthemostcomplexcodeandconceptsintheentirelesson.Ifyouareabeginner,youmaywanttojumpaheadtotheBuildinganApplicationsection.

Thefunctionswithinthegppoly.lspfileareorganizedinawaythatyoumayhavenoticedinotherAutoLISPsourcecodefiles.Thehighest-levelfunction,oftenthemain,orC:function(inthiscase,gp:Redefine-PolyBorder),islocatedatthebottomofthefile.Thefunctionscalledwithinthemainfunctionaredefinedaboveitwithinthesourcefile.Thisconventiongoesbacktotheolddaysofprogramming,whensomedevelopmentenvironmentsrequiredthatfilesbeorganizedthisway.WithVLISP,thisisamatterofpersonalstyle;thereisnorequirementthatyouorganizeyourfunctionsinanyspecificsequence.

Beforedivingintothedetails,stepbackandlookatwhatneedstobedonetorecalculateanddrawthegardenpathboundary.Thefollowingillustrationshowsanexampleofagardenpath,alongwiththeassociationlistkeypointsstoredinthereactordata:

Page 192: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Inthisexample,the12keypointisthelower-leftcorner,13islower-right,andsoon.Iftheusermovestheupper-rightpoint(the14keypoint),theprogramwillneedtorecalculatetwoexistingpoints—thelower-right(13)andupper-left(15).

Pleasesendusyourcommentaboutthispage

Page 193: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>RedefiningthePolylineBoundary>

Understandingthegp:RedefinePolyBorderFunction

Thefollowingpseudo-codeshowsthelogicbehindthemainfunction,gp:RedefinePolyBorder:

Functiongp:RedefinePolyBorder

Extractthepreviouspolylinecornerpoints(12,13,14,and15

keyvalues).

Findthemovedcornerpointbycomparingtheprevious

polylinecornerpointswiththecurrentcornerpoints.

(Theone"misfit"pointwillbethepointthatmoved.)

Setthenewcornerpointsbyrecalculatingthetwopoints

adjacenttothemovedpoint.

Updatethenewcornerpointsinthereactordata(thatwill

bestoredbackinthereactorforthemodifiedpolyline).

Updateotherinformationinthereactordata.(Startpoint,

endpoint,width,andlengthofpathneedtoberecalculated.)

Pleasesendusyourcommentaboutthispage

Page 194: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>RedefiningthePolylineBoundary>

Understandingthegp:FindMovedPointFunction

Thegp:FindMovedPointfunctioncontainssomeverypowerfulLISPexpressionsdealingwithlistmanipulation.Essentially,whatthisfunctiondoesiscomparethelistofthecurrentpolylinepoints(aftertheuserdraggedonetoanewlocation)tothepreviouspoints,andreturnthekeyedlist(the13<xvalue><yvalue>)forthemovedpoint.

Thebestwaytofigureouthowthisfunctionworksistostepthroughthecodeandwatchthevaluesthatitmanipulates.Setabreakpointrightatthefirstexpression(setqresult...)andwatchthefollowingvariableswhileyoustepthroughthefunction:

KeyListToLookFor

PresentPoints

KeyedList

Result

KeyListStatus

MissingKey

MovedPoint

Themapcarandlambdafunctionswillbeexaminedinthefollowingsection.Fornow,however,followthecommentsinthecodetoseeifyoucanunderstandwhatishappeningwithinthefunctions.

Pleasesendusyourcommentaboutthispage

Page 195: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>RedefiningthePolylineBoundary>

Understandingthegp:FindPointInListFunction

Thefunctionheaderinthesourcecodeexplainshowgp:FindPointInListtransformstheinformationitworkswith.Likethepreviousfunction,Gp:FindMovedPoint,thisfunctionusesLISP'slistmanipulationcapabilitiestoperformthework.Whenoperatingwithlists,youwilloftenseethemapcarandlambdafunctionsusedtogetherastheyarehere.Atfirst,thesearestrangeandconfusingfunctions,withnamesthatdonotindicatewhattheydo.Onceyoulearnhowtousethem,however,youwillfindthemtobetwoofthemostpowerfulfunctionswithintheAutoLISPrepertoire.Whatfollowsisabriefoverviewofmapcarandlambda.

Themapcarfunctionapplies(maps)anexpressiontoeveryiteminalist.Forexample,givenalistoftheintegers1,2,3,and4,mapcarcanbeusedtoapplythe1+functiontoadd1toeachnumberinthelist:

_$(mapcar'1+'(1234))(2345)

Aninitialdefinitionformapcaristhatitmapsthefunctiongiveninthefirstparametertothesuccessiveitemsinthesecondparameter—thelist.Theresultingvaluefromamapcaroperationisthelisttransformedbywhateverfunctionorexpressionwasappliedtoit.(Actually,mapcarcandomorethanthat,butfornowthisdefinitionwillsuffice.)

Inthesuppliedexample,everyvalueinthelist'(1234)waspassedtothe1+function.Essentially,mapcarperformedthefollowingoperations,assemblingtheresultingvaluesinalist:

(1+1)->2

(1+2)->3

(1+3)->4

(1+4)->5

Page 196: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Hereisanotherexampleofmapcar,thistimeusingthenullfunctiontotestwhetherornotthevaluesinalistarenull(nottrue)values:

_$(mapcar'null(list1

(=3"3")nil"Steve"))(nilTTnil)

Whathappenedinthiscodewasessentiallythefollowing:

(null1)->nil

(null(=3"3")->T

(nullnil)->T

(null"Steve")->nil

YoucanusemanyexistingAutoLISPfunctionswithinamapcar.Youcanalsouseyourownfunctions.Forexample,imagineyouhavejustcreatedaverypowerfulfunctionnamedequals2:

_$(defunequals2(num)(=

num2))EQUALS2

_$(mapcar'equals2'(1

234))(nilTnilnil)

Okay,soequals2isnotallthatpowerful.Butitisinsuchcasesthatlambdacomesinhandy.Youcanuselambdaincaseswhereyoudonotwantorneedtogothroughtheoverheadofdefiningafunction.Youwillsometimesseelambdadefinedasananonymousfunction.Forexample,insteadofdefiningafunctioncalledequals2,youcouldwritealambdaexpressiontoperformthesameoperationwithouttheoverheadofthefunctiondefinition:

_$(mapcar'(lambda(num)

(=num2))'(1234))(nilTnilnil)

Whathappenedinthecodewasthis:

(=12)->nil

(=22)->T

(=32)->nil

(=42)->nil

Page 197: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

Withthisknowledge,seeifthegp:FindPointInListfunctionmakessense.Again,reviewthecommentswithinthesourcecode.

Pleasesendusyourcommentaboutthispage

Page 198: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>RedefiningthePolylineBoundary>

Understandingthegp:recalcPolyCornersFunction

Thekeytounderstandinghowgp:recalcPolyCornersworksistorevisitthediagramshowingwhatthekeyvaluesof12through15represent:

Inthediagram,theusermovedthecornerpointassociatedwiththekeyvalueof14.Thismeansthecornerpointsassociatedwith13and15needtoberecalculated.

Point15needstobemovedalongthecurrentvectordefinedbypoint12topoint15untilitlinesupwiththenewpoint14.Thevectorsfrom12to15,andfrom14to15,mustbeperpendiculartoeachother.Thesameoperationmustbeappliedtorecalculatethenewlocationforpoint13.

Nowtakeanotherlookatthecodetoseeifitmakessense.

Pleasesendusyourcommentaboutthispage

Page 199: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>RedefiningthePolylineBoundary>

Understandingthegp:pointEqual,gp:rtos2,andgp:zeroSmallNumFunctions

ThesethreefunctionsarerequiredtogetaroundoneofthequirksofprogramminginanAutoCADsystem,which,asyouarewellaware,allowsyouagreatdealofprecision.Occasionally,though,numbersarenotquitepreciseenough,duetotheroundingupordownoffloatingpointvaluesdefininggeometricpositions.Youmustbeabletocompareonesetofpointswithotherpoints,soyoumustdealwiththesecases.

Haveyouevernoticedthatoccasionally,whenyoulisttheinformationassociatedwithanAutoCADentity,youseeavaluesuchas1.0e-017?Thisnumberisalmostzero,butwhenyouarecomparingittozerowithinaLISPprogram,almostdoesnotcount.

Withinthegardenpath,youneedtobeabletocomparenumberswithouthavingtoworryaboutthefactthat1.0e-017isnotquitezero.Thegp:pointEqual,gp:rtos2,andgp:zeroSmallNumfunctionshandleanydiscrepanciesinroundingwhencomparingpointlists.

Thiscompletesyourtourofthefunctionsingppoly.lsp.

Pleasesendusyourcommentaboutthispage

Page 200: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>

WrappingUptheCode

Sofar,youhavedonethefollowinginthislesson:

Modifiedthegp:drawOutlinefunctionsothatitreturnsthepolylineperimeterpointsinadditiontothepointertothepolyline.Youaddedthisinformationtothegp_PathDatavariable.Thisvariableisstoredwiththereactordataintheobjectreactorattachedtoeverygardenpath.

Updatedthereactorfunctionsingpreact.lsp.

AddedfunctionsxyzList->ListOfPoints, xyList->ListOfPoints,andotherutilityfunctionstotheutils.lspfile.

Updatedthegp:Calculate-and-Draw-TilesfunctionsothatObjectCreationStyleisnowaparametertothefunctionratherthanalocalvariable.

Modifiedthecalltogp:Calculate-and-Draw-TilesintheC:GPathfunctionwithinthegpmain.lspfile.

Addedgppoly.lsptoyourproject,andexaminedthefunctionswithinit.

Givethecompletedapplicationatry.Saveyourwork,thenloadintheprojectsources,runtheGpathfunction,andtrystretchingandmovingthegardenpathboundary.Remember:ifsomethingisnotworkingandyouareunabletodebugtheproblem,youcanloadthecompletedcodefromtheTutorial\VisualLISP\Lesson7directory.

Pleasesendusyourcommentaboutthispage

Page 201: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>

BuildinganApplication

Thefinalactwithinthistutorialistotakeyourgardenpathcodeandturnitintoastand-aloneapplication.Thisway,itcanbedistributedasasingleexecutabletoanyuserorcustomer.Fortunately,thislastsetoftasksisprobablytheeasiestinthisentiretutorial,asVLISPdoespracticallyalltheworkforyou.

Note Itisrecommendedthatyouproceedwithbuildinganapplicationonlyifyourcodeisingoodworkingform.Makesurethatyouhavetestedyourapplicationusingtheoriginalsourcefiles,andthatyouaresatisfiedwiththeresults.

Topicsinthissection

StartingtheMakeApplicationWizard

Pleasesendusyourcommentaboutthispage

Page 202: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>BuildinganApplication>

StartingtheMakeApplicationWizard

Toassistyouincreatingstandaloneapplications,VLISPprovidestheMakeApplicationwizard.

ToruntheMakeApplicationwizard

1. Tostartthewizard,chooseFile MakeApplication NewApplicationWizardfromtheVLISPmenu.

2. SelectExpertmodeandchooseNext.ThewizardpromptsyoutospecifythedirectoryinwhichtostorefilescreatedbyMakeApplication,andtonameyourapplication.MakeApplicationproducestwooutputfiles:a.vlxfilecontainingyourprogramexecutable,anda.prvfilecontainingtheoptionsyouspecifytoMakeApplication.The.prvfileisalsoknownasamakefile.Youcanusethemakefiletorebuildyourapplication,whennecessary.

3. SpecifyyourTutorial\VisualLISP\MyPathdirectoryastheapplicationlocation,andcalltheapplicationgardenpath.VLISPusestheapplicationnameintheoutputfilenames(inthisinstance,gardenpath.vlxandgardenpath.prv.)ChooseNexttocontinue.

4. Theapplicationoptionsarenotcoveredinthistutorial.AcceptthedefaultsandchooseNext.(Forinformationonseparatenamespaceapplications,see“RunninganApplicationinItsOwnNamespace”intheAutoLISPDeveloper'sGuide.)

5. Inthisstep,thewizardispromptingyoutoidentifyalltheAutoLISPsourcecodefilesthatmakeuptheapplication.YoucouldindividuallyselecttheLISPsourcefiles,butthereisaneasierway.Changethepull-downfiletypeselectionboxsothat“VisualLISPProjectfile”isshown,

Page 203: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

thenchoosetheAddbutton.SelecttheGpathprojectfileandchooseOpen.Note Dependingonhowyouworkedthroughthetutorial,youmayhaveseveralGpathprojectfilesshowingup.Selectthemostrecentfile.IfyoucopiedinthecompletedsourcecodefromLesson7,theprojectnametoselectshouldbeGpath7.prj.

Afterselectingtheprojectfile,chooseNexttocontinue.OneadvantageofcompiledVLXapplicationsisthatyoucancompileyourdialogcontrolfiles(.dcl)intothecompleteapplication.Thisreducesthenumberofindividualsourcefilesyourendusersneedtodealwith,andeliminatesanyofthesearchpathproblemswhenloadingaDCLfile.

6. Changethepull-downfiletypeselectionboxsothat“DCLfiles”isshown,thenchoosetheAddbutton.Selectthegpdialog.dclfile,thenchooseOpen.ChooseNexttocontinuebuildingtheapplication.

7. Compilationoptionsarenotcoveredinthistutorial.AcceptthedefaultsandchooseNext.(Forinformationoncompileoptions,see“OptimizingApplicationCode”intheAutoLISPDeveloper'sGuide.)

8. Thefinalstepisusedtoreviewtheselectionsyou'vemade.Atthispoint,youcanselectFinish.VLISPwillbeginthebuildprocess,displayingtheresultsintheBuildOutputwindow.Severalintermediatefileswillbeproduced,asyourindividualsourcecodefilesarecompiledintoaformatthatcanbelinkedintothesingleVLXapplication.

Whenitisallcomplete,you'llhaveanexecutablefilenamedgardenpath.vlx.Totestit,dothefollowing:

FromtheToolsmenuinAutoCAD,selectLoadApplication.

Loadthegardenpath.vlxapplicationthatwasjustcreatedandisfoundintheTutorial\VisualLISP\MyPathdirectory.

Runthegpathcommand.

Pleasesendusyourcommentaboutthispage

Page 204: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>

WrappingUptheTutorial

Youhavefinallymadeittotheendofthepath!Asyouhavediscovered,alotofmaterialwascoveredinthistutorial.BothAutoLISPconceptsandVLISPoperationshavebeenintroduced.The“gardenpathrevisited”wasdesignedtogiveyouasamplingofmanytopicsandconcepts.Youmightbeinterestedinmoreinformation.ThefollowingisabriefbibliographyofsomecommonLISPandAutoLISPbooks.

Pleasesendusyourcommentaboutthispage

Page 205: Introduction - documentation.help · Introduction > Working in Visual LISP This tutorial assumes you have some familiarity with LISP or AutoLISP. It also assumes you understand basic

PuttingItAllTogether>

LISPandAutoLISPBooks

UnderstandingAutoLISP:ProgrammingforProductivity,WilliamKramer,AutodeskPress,ISBN0-8273-5832-6.

AutoLISPinPlainEnglish:APracticalGuideforNon-Programmers,GeorgeO.Head,VentanaPress,ISBN:1566041406.

LISP,3rdEdition,PatrickHenryWinstonandBertholdKlausPaulHorn,Addison-WesleyPublishingCompany,ISBN0-201-08319-1.

ANSICommonLisp,PaulGraham,PrenticeHall,ISBN0-13-370875-6.

CommonLISP,TheLanguage,SecondEdition,GuyL.Steele,Jr.,DigitalPress,ISBN1-55558-041-6.

Pleasesendusyourcommentaboutthispage