Top Banner
utoLISP Tutorial > 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. Working in Visual LISP Tutorial Overview Please send us your comment about this page
206

AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Apr 18, 2020

Download

Documents

dariahiddleston
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>

Introduction

ThistutorialisdesignedtodemonstrateseveralpowerfulcapabilitiesoftheAutoLISP®programmingenvironmentforAutoCAD®andintroducefeaturesoftheAutoLISPlanguagethatmaybenewtoyou.

Thepurposeofthetutorialistodrawagardenpathusinganautomateddrawingtoolthatminimizesdraftingtimeandshowsthepowerofparametricprogramming.Youwilllearntocreateadrawingroutinethatautomatesthegenerationofacomplexshape—thekindofdraftingoperationyoudonotwanttohavetodomanuallyoverandoveragain.

WorkinginVisualLISPTutorialOverview

Pleasesendusyourcommentaboutthispage

Page 2: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>Introduction>

WorkinginVisualLISP

ThistutorialisintendedforexperiencedAutoCADusersandassumesyouhavesomefamiliaritywithLISPorAutoLISP.ItalsoassumesyouunderstandbasicWindows®filemanagementtaskssuchascreatingdirectories,copyingfiles,andnavigatingthroughthefilesystemonyourharddiskornetwork.

Inthistutorial

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

ActiveX®andReactorfunctionsofAutoLISParedemonstrated,aswellasseveralotherextensionstotheAutoLISPlanguageprovidedwithVLISP.

Therearethefollowingtwopossibleexecutioncontextsforthistutorial:

TheapplicationmayberunasinterpretedLISPinpiecemealfilesand/orfunctionsthatareloadedintoasingledocument,or

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

Pleasesendusyourcommentaboutthispage

Page 3: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>Introduction>

TutorialOverview

YourgoalinthistutorialistodevelopanewcommandforAutoCADthatdrawsagardenpathandfillsitwithcirculartiles.Thetutorialisdividedintosevenlessons.Asyouprogressfromlessontolesson,youreceiveprogressivelylessdetailedinstructionsonhowtoperformindividualtasks.HelpisavailableintheVLISPdocumentationifyouhaveanyquestions.

Lessons4and5areatanintermediatelevelandgobeyondbasicAutoLISPconcepts.Lessons6and7containadvancedandfairlycomplexprogrammingtasksandaredesignedforexperiencedAutoLISPdevelopers.

IfyouchosethefullinstallationoptionwhenyouinstalledAutoCAD,thesourcecodefilesareinthefollowingdirectory:

<AutoCADdirectory>\Tutorial\VisualLISP\

IfyouhavealreadyinstalledAutoCADanddidnotinstallthesamples,youcanreruntheinstallation,chooseCustom,andselectonlytheTutorialsitem.

ItisrecommendedyoudonotmodifythesamplesourcecodefilessuppliedwithAutoCAD.Ifsomethingisnotworkingcorrectlywithinyourprogram,youmaywanttocopythesuppliedsourcecodeintoyourworkingdirectory.Throughoutthetutorial,theworkingdirectoryisreferredtoas:

<AutoCADdirectory>\Tutorial\VisualLISP\MyPath

Ifyouchooseadifferentpathforyourworkingdirectory,substituteyourdirectorynameattheappropriatetimes.

Pleasesendusyourcommentaboutthispage

Page 4: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>

DesigningandBeginningtheProgram

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

DefiningOverallProgramGoalsGettingStartedwithVisualLISPLookingatVisualLISPCodeFormattingAnalyzingtheCodeFillingtheGapsintheProgramLettingVisualLISPCheckYourCodeRunningtheProgramwithVisualLISPWrappingUpLesson1

Pleasesendusyourcommentaboutthispage

Page 5: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DesigningandBeginningtheProgram>

DefiningOverallProgramGoals

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

Yourprogrammustdothefollowingtodrawthegardenpath:

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

Prompttheuserfortilesizeandtilespacingvalues.Thetilesaresimplecirclesandwillfilltheboundarybutmustnotoverlaporcrosstheboundary.

Placethetilesinalternatingrows.

Page 6: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DesigningandBeginningtheProgram>

LookingatVisualLISPCodeFormatting

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

Asyouentertext,VLISPalsoformatsitbyaddingspacingandindentation.TogetVLISPtoformatcodeyoucopyintoitstexteditorfromanotherfile,chooseTools FormatCodeinEditorfromtheVLISPmenu.

Pleasesendusyourcommentaboutthispage

Page 10: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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:getDialogInputwillgetuserchoicesviaadialog"

)

Page 12: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

;;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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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

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

Pleasesendusyourcommentaboutthispage

Page 15: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DesigningandBeginningtheProgram>

WrappingUpLesson1

Inthislesson,you

Definedprogramgoals.

Learnedthevalueofstubfunctions.

Learnedaboutnamingfunctionstoidentifythemasspecifictoyourapplicationorasgeneralfunctionstobeusedoverandover.

LearnedhowtouseVLISPtocheckyourcode.

LearnedhowtoloadandrunaprograminVLISP.

Youaredonewiththislesson.Saveyourprogramfileagaintobecertainyouhavethelatestrevisions.

Pleasesendusyourcommentaboutthispage

Page 17: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>

UsingVisualLISPDebuggingTools

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

DifferentiatingBetweenLocalandGlobalVariablesUsingAssociationListstoBundleDataExaminingProgramVariablesRevisingtheProgramCodeCommentingProgramCodeSettingaBreakpointandUsingMoreWatchesWrappingUpLesson2

Pleasesendusyourcommentaboutthispage

Page 18: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

partoftheprogramaffectingavariablefromanotherpartoftheprogram).

Becauseoftheadvantagescited,thistutorialuseslocalvariablesalmostexclusively.

Note IfyouhavebeenworkingwithAutoLISPforsometime,youmayhavedevelopedthepracticeofusingglobalvariablesduringdevelopmenttoexamineyourprogramwhileyouarebuildingit.Thispracticeisnolongernecessary,giventhepowerfuldebuggingtoolsofVLISP.

UsingLocalVariablesintheProgramExaminingthegp:getPointInputFunction

Pleasesendusyourcommentaboutthispage

Page 20: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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

PuttingAssociationListstoUse

Page 25: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

StoringtheReturnValueofgp:getPointInputinaVariable

Pleasesendusyourcommentaboutthispage

Page 26: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

)

)

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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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

3. Double-clickonthelinewiththeassociationlistkey11.VLISPopensanotherInspectwindow:

4. Whenyouaredoneinspectingvariables,closealltheInspectwindowsbutkeeptheWatchwindowopen.

Pleasesendusyourcommentaboutthispage

Page 31: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

(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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

;;;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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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

Pleasesendusyourcommentaboutthispage

Page 35: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>UsingVisualLISPDebuggingTools>

SettingaBreakpointandUsingMoreWatches

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

Whileyourprogramissuspended,youcan

Stepthroughyourcode,functionbyfunction,orexpressionbyexpression.

Resumenormalexecutionofyourprogramatanypoint.

Alterthevalueofvariablesdynamically,andchangetheresultsoftheprogrambeingexecuted.

AddvariablestotheWatchwindow.UsingtheDebugToolbarSteppingThroughCodeWatchingVariablesAsYouStepThroughaProgramSteppingOutofthegp:getPointInputFunctionandintoC:Gpmain

Pleasesendusyourcommentaboutthispage

Page 37: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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

6. Specifythestartpointandendpointwhenprompted.Afteryouspecifythepoints,VLISPsuspendsexecutionoftheprogramandreturnsfocustothetexteditorwindow,highlightingthelineofcodeatthebreakpointposition:

Thereareacoupleofthingstonotice:

Thecursorislocatedrightatthebreakpoint.Thismaybedifficulttonotice,soVLISPprovidesanotherclue.

IntheDebugtoolbar,theStepIndicatoricondisplaysaredI-beamcursorinfrontofapairofparentheses.ThisindicatestheVLISPdebuggerisstoppedbeforetheexpression.

Page 40: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Pleasesendusyourcommentaboutthispage

Page 41: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

nextblockofcode,andhighlightstheentireblock.

4. ChoosetheStepInto(notStepOver)button.

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

Nowthefirstconsfunctionishighlighted,andVLISPisstoppedrightbeforethefunction(noticetheStepIndicatorbutton).

Pleasesendusyourcommentaboutthispage

Page 43: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Tocompletethislesson

1. ChoosetheContinuebuttonontheDebugtoolbar.Respondtotheprompts.Thisrunstheprogramtocompletion.

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

Pleasesendusyourcommentaboutthispage

Page 47: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>UsingVisualLISPDebuggingTools>

WrappingUpLesson2

Inthislesson,you

Learnedaboutlocalandglobalvariables.

Setandremovedbreakpointsinaprogram.

Steppedthroughaprogramwhileitwasexecuting.

Watchedanddynamicallychangedthevalueofprogramvariablesduringexecution.

Sawhowlocalvariablesareresettonilafterthefunctionthatdefinedthemcompletesitsrun.

ThetoolsyoulearnedinthislessonwillbepartofyourdailyworkifyouintendtodevelopAutoLISPapplicationswithVLISP.

Pleasesendusyourcommentaboutthispage

Page 48: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>

DrawingthePathBoundary

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

PlanningReusableUtilityFunctionsDrawingAutoCADEntitiesEnablingtheBoundaryOutlineDrawingFunctionWrappingUpLesson3

Pleasesendusyourcommentaboutthispage

Page 49: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingthePathBoundary>

PlanningReusableUtilityFunctions

Utilityfunctionsperformtaskscommontomanyapplicationsyouwillbewriting.Thesefunctionsformatoolkityoucanuseoverandoveragain.

Whenyoucreateafunctionaspartofatoolkit,spendsometimedocumentingitthoroughly.Inyourcomments,alsonotethefeaturesyouwouldliketoaddtothefunctioninthefuture,shouldtimepermit.

ConvertingDegreestoRadiansConverting3DPointsto2DPoints

Pleasesendusyourcommentaboutthispage

Page 50: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Pleasesendusyourcommentaboutthispage

Page 55: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingthePathBoundary>

DrawingAutoCADEntities

MostAutoLISPprogramsdrawentitiesusingoneofseveralmethods:

ActiveXfunctions

Theentmakefunction

Thecommandfunction

ThislessonfocusesonentitycreationviaActiveX®.InLesson5,youwillimplementtheentmakeandAutoCADcommandalternatives.

CreatingEntitiesUsingActiveXFunctionsUsingentmaketoBuildEntitiesUsingtheAutoCADCommandLine

Pleasesendusyourcommentaboutthispage

Page 56: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingthePathBoundary>DrawingAutoCADEntities>

CreatingEntitiesUsingActiveXFunctions

ThenewestwayofcreatingentitiesisbyusingtheActiveXfunctionswithinVLISP.ActiveXhasseveraladvantagesoverentmakeandcommand.

ActiveXfunctionsarefaster.

ActiveXfunctionnamesindicatetheactiontheyperform,resultingineasierreadability,maintenance,andbug-fixing.

YouwillseeanexampleofanActiveXfunctionlaterinthislesson.

Pleasesendusyourcommentaboutthispage

Page 57: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingthePathBoundary>DrawingAutoCADEntities>

UsingentmaketoBuildEntities

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

Pleasesendusyourcommentaboutthispage

Page 58: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingthePathBoundary>DrawingAutoCADEntities>

UsingtheAutoCADCommandLine

WhenAutoLISPfirstappearedinAutoCAD,theonlyavailablemeansforentitycreationwasthecommandfunction.ThisallowsanAutoLISPprogrammertocodejustaboutanycommandthatcanbeexecutedfromtheAutoCADCommandprompt.Thisisreliable,butitisnotasfastasActiveXmethodsanddoesnotprovidetheflexibilityofentmake.

Pleasesendusyourcommentaboutthispage

Page 59: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

variableisdefinedandwhatitisusedfor.Butifthefunctionsaredefinedindifferentfiles—asisoftenthecase—youwouldhavetosearchthroughbothfilestofigureoutwhatgp_PathDatarepresents.

PassingParameterstoFunctionsWorkingwithanAssociationListUsingAnglesandSettingUpPointsUnderstandingtheActiveXCodeingp:drawOutlineEnsuringThatActiveXIsLoadedObtainingaPointertoModelSpaceConstructinganArrayofPolylinePointsConstructingaVariantfromaListofPointsPuttingItAllTogether

Pleasesendusyourcommentaboutthispage

Page 61: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingthePathBoundary>EnablingtheBoundaryOutlineDrawingFunction>

PassingParameterstoFunctions

Abetterwaytoconveyinformationfromonefunctiontoanotheristopassparameterstothecalledfunction.Designthefunctionsoitexpectstoreceiveanumberofvalues.RemembertheDegrees->Radiansfunction?ThisfunctionispassedaparameternamednumberOfDegrees:

(defunDegrees->Radians(numberOfDegrees)

(*pi(/numberOfDegrees180.0)))

Whenyoucallthefunction,itexpectsyoutopassitanumber.ThenumberwithinDegrees->RadiansisdeclaredastheparameternamednumberOfDegrees.Forexample:

_$(degrees->radians

90)1.5708

Inthiscase,thenumber90isassignedtotheparameternumberOfDegrees.

Youcanalsopassavariabletoafunction.Forexample,youmighthaveavariablecalledaDegreeValuethatcontainsthenumber90.ThefollowingcommandssetaDegreeValueandpassthevariabletoDegrees->Radians:

_$(setqaDegreeValue

90)90

_$(degrees->radians

aDegreeValue)1.5708

Page 62: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Pleasesendusyourcommentaboutthispage

Page 63: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 64: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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 65: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 66: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

(setqp1(polarStartPtangm90HalfWidth)

p2(polarp1PathAnglePathLength)

p3(polarp2angp90Width)

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

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

Pleasesendusyourcommentaboutthispage

Page 67: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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-methodcallis

Page 68: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

theobjectbeingmodifiedorqueried,forexample,*ModelSpace*inthefirstfunctioncallandplineinthesecondcall.

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

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

Pleasesendusyourcommentaboutthispage

Page 69: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingthePathBoundary>EnablingtheBoundaryOutlineDrawingFunction>

EnsuringThatActiveXIsLoaded

ActiveXfunctionalityisnotautomaticallyenabledwhenyoustartAutoCADorVLISP,soyourprogramsmustensurethatActiveXisloaded.Thefollowingfunctioncallaccomplishesthis:

(vl-load-com)

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

Pleasesendusyourcommentaboutthispage

Page 70: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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)

Page 71: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Thefunctionisdefinitelylessunderstandable.Notonlythat,butwithineveryexpressionwithinyourprogramwhereanentityiscreated,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 72: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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,youcanuse

Page 73: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

thefollowingexpression:

(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 74: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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-variantiscalledtoconvertthesafearrayintoa

Page 75: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

variant.Asthelastfunctioncallingp:list->variantArray,thereturnvalueispassedtothecallingfunction.

Thefollowingisanexampleofafunctioncallthatinvokesgp:list->variantArraytoconvertalisttoavariantarrayofdoubles:

;dataconversionfromlisttovariant

(setqVLADataPts(gp:list->variantArraypolypoints))

Pleasesendusyourcommentaboutthispage

Page 76: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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)

Page 77: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

polypoints(apply'append

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

)

)

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

;;Notice,polypointsisinAutoLISPformat,consistingofalist

;;ofthe4cornerpointsforthegardenpath.

;;Thevariableneedstobeconvertedtoaformofinputparameter

;;acceptabletoActiveXcalls.

(setqVLADataPts(gp:list->variantArraypolypoints))

;;AddpolylinetothemodelspaceusingActiveXautomation.

(setqpline(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*

Page 78: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

(vla-get-ModelSpace

(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 79: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingthePathBoundary>

WrappingUpLesson3

Inthislesson,you

Wroteutilityfunctionsthatcanbereusedinotherapplications.

Addedentitycreationlogictoyourprogram.

LearnedhowtouseActiveXfunctions.

Learnedhowtoworkwithassociationlists.

Enabledyourprogramtodrawagardenpathborder.

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

Pleasesendusyourcommentaboutthispage

Page 80: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>

CreatingaProjectandAddingtheInterface

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

Fromthislessonon,thetutorialprovidesmoregeneraldescriptionsofthetasksyouneedtoperform,unlessnewtopicsarecovered.Also,thecodefragmentswillbeminimallydocumentedtosavespace.

ModularizingYourCodeUsingVisualLISPProjectsAddingtheDialogBoxInterfaceInteractingwiththeDialogBoxfromAutoLISPCodeProvidingaChoiceofBoundaryLineTypeCleaningUpRunningtheApplicationWrappingUpLesson4

Pleasesendusyourcommentaboutthispage

Page 81: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 82: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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 83: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 84: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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

6. ChooseOK.

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

Pleasesendusyourcommentaboutthispage

Page 85: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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.

DefiningtheDialogBoxwithDCLSavingaDCLFilePreviewingaDialogBox

Pleasesendusyourcommentaboutthispage

Page 86: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>CreatingaProjectandAddingtheInterface>AddingtheDialogBoxInterface>

DefiningtheDialogBoxwithDCL

Beginbytakingalookatthedialogboxyouneedtocreate.

Thedialogboxcontainsthefollowingelements:

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

Editboxesforspecifyingtheradiusoftilesandthespacingbetweentiles.

AstandardsetofOKandCancelbuttons.

DialogboxcomponentsarereferredtoastilesinDCL.WritingthecompletecontentsofadialogboxDCLfilemayseemoverwhelming.Thetrickisto

Page 87: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

sketchoutwhatyouwant,breakitdownintosections,thenwriteeachsection.

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:

Page 88: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

:boxed_radio_column{//definestheradiobuttonareas

label="TileCreationMethod";

: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";

Page 89: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

is_cancel=true;

key="cancel";

width=8;

fixed_width=true;

}

:spacer{width=1;}

}

Bothbuttonsaredefinedwithinarow,sotheylineuphorizontally.

7. ScrolltothebeginningofthetexteditorwindowandinsertthefollowingstatementasthefirstlineinyourDCL:

gp_mainDialog:dialog{

8. Thedialogdirectiverequiresaclosingbrace,soscrolltotheendofthefileandaddthebraceasthelastlineofDCLcode:

}

Pleasesendusyourcommentaboutthispage

Page 90: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 91: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 92: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>CreatingaProjectandAddingtheInterface>

InteractingwiththeDialogBoxfromAutoLISPCode

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

Developingadialogboxinterfacecanbeconfusingthefirstfewtimesyoudoit.Itinvolvesplanningaheadandaskingyourselfsuchquestionsas:

Doesthedialogboxneedtobesetupwithdefaultvalues?

Whathappenswhentheuserchoosesabuttonorentersavalue?

WhathappenswhentheuserchoosesCancel?

Ifthedialog(.dcl)fileismissing,whatneedstooccur?SettingUpDialogValuesLoadingtheDialogFileLoadingaSpecificDialogintoMemoryInitializingtheDefaultDialogValuesAssigningActionstoTilesStartingtheDialogUnloadingtheDialogDeterminingWhattoDoNextPuttingtheCodeTogetherUpdatingaStubbed-OutFunction

Pleasesendusyourcommentaboutthispage

Page 93: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Pleasesendusyourcommentaboutthispage

Page 97: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

assignedtothevariableUserClick.

You'redoneassigningactionstothebuttons.Thenextthingtodoistoputitallinmotion.

Pleasesendusyourcommentaboutthispage

Page 101: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

StartingtheDialog

Thestart_dialogfunctiondisplaysadialogboxandacceptsuserinput.Thestart_dialogfunctionrequiresnoarguments.

(start_dialog)

Controlpassestouserswhenyouissuestart_dialog.Userscanmakechoiceswithinthedialogbox,untiltheychoosetheOKorCancelbuttons.

Pleasesendusyourcommentaboutthispage

Page 102: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

UnloadingtheDialog

WhenauserchoosestheOKorCancelbutton,youneedtounloadthedialog.Likestart_dialog,unload_dialogisanothersimplefunction.

(unload_dialogdcl_id)

Pleasesendusyourcommentaboutthispage

Page 103: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>CreatingaProjectandAddingtheInterface>InteractingwiththeDialogBoxfromAutoLISPCode>

DeterminingWhattoDoNext

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

(ifUserClick;UserclickedOk

;;Buildtheresultingdata

(progn

(setqResult(list

(cons42tileRad)

(cons43TileSpace)

(cons3objectCreateMethod)

(cons4plineStyle)

)

)

)

)

Pleasesendusyourcommentaboutthispage

Page 104: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

notthefragmentsintheexplanationsthatfollow.Thosefragmentsjustrepeatpiecesoftheexample.

StartingtheDialog

UnloadingtheDialog

DeterminingWhattoDoNext

5. Afterthelastlineofcode,addthefollowing:

)

)

Result;

);_endofdefun

6. FormatthecodeyouenteredbychoosingTools FormatCodeinEditorfromtheVLISPmenu.

Pleasesendusyourcommentaboutthispage

Page 106: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

(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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

);_endofvla-addLightweightPolyline

;;orcreateanold-stylepolyline

(vla-addPolyline

*ModelSpace*

(gp:list->variantArraypoly3Dpoints);dataconversion

);_endofvla-addPolyline

);_endofif

);_endofsetq

Typingthechangesintoyourcodecanbeverytricky,asyounotonlyneedtoaddcodebutalsotodeletesomeexistinglinesandrearrangeothers.Itisrecommendedyoucopytheentiresetqstatementfromtheonlinetutorialandpasteitintoyourcode.

Pleasesendusyourcommentaboutthispage

Page 110: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>CreatingaProjectandAddingtheInterface>

CleaningUp

Ifyouhavenotdonesoalready,deletethefollowingcodefromtheC:GPathfunctioningpmain.lsp:

(princ"\nThegp:drawOutlinefunctionreturned<")

(princPolylineName)

(princ">")

(Alert"Congratulations-yourprogramiscomplete!")

Youhadbeenusingthiscodeasaplaceholder,butnowthatgp:drawOutlineisfunctioning,younolongerneedit.

Pleasesendusyourcommentaboutthispage

Page 111: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>CreatingaProjectandAddingtheInterface>

WrappingUpLesson4

Inthislesson,you

Modularizedyourcodebydividingitamongfourfiles.

OrganizedyourcodemodulesinaVLISPproject.

Learnedtodefineadialogboxwithdialogcontrollanguage(DCL).

AddedAutoLISPcodetosetupandhandleinputinthedialogbox.

Modifiedyourcodetoprovideuserswithachoiceofboundarylinetype.

Nowyouhaveaprogramthatdrawsagardenpathboundary.Inthenextlesson,youwilladdthetilestothegardenpath.Intheprocess,youwillbeintroducedtomoreVLISPprogramdevelopmenttools.

Pleasesendusyourcommentaboutthispage

Page 113: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>

DrawingtheTiles

Bytheendofthislesson,yourapplicationwillmeetthebasicrequirementsstatedinLesson1.Youwilladdthefunctionalityfordrawingtileswithintheboundaryofthegardenpathandprovidethisfunctionusingseveraldifferentmethodsofentitycreation.Youwillalsolearnsomekeyboardshortcutsandneweditingtools.

IntroducingMoreVisualLISPEditingToolsAddingTilestotheGardenPathTestingtheCodeWrappingUpLesson5

Pleasesendusyourcommentaboutthispage

Page 114: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingtheTiles>

IntroducingMoreVisualLISPEditingTools

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

MatchingParenthesesCompletingaWordAutomaticallyCompletingaWordbyAproposGettingHelpwithaFunction

Pleasesendusyourcommentaboutthispage

Page 115: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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.

Page 116: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Pleasesendusyourcommentaboutthispage

Page 117: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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:

Page 118: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

(progn

(setqfirstCenterPt(p

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

6. Deleteallthecodeyoujustentered;itwasfordemonstrationpurposesonly.TheCompleteWordbyMatchfeatureisalsoavailablefromtheVLISPSearchmenu.

Pleasesendusyourcommentaboutthispage

Page 119: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 120: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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.

Page 121: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Pleasesendusyourcommentaboutthispage

Page 122: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingtheTiles>

AddingTilestotheGardenPath

Younowhaveapathboundaryandarereadytofillitwithtiles.Youwillneedtoapplysomelogicandworkthroughalittlegeometry.

ApplyingSomeLogicApplyingSomeGeometryDrawingtheRowsDrawingtheTilesinaRowLookingattheCode

Pleasesendusyourcommentaboutthispage

Page 123: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 124: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Resetthenextstartpoint(incrementedbyone"tilespace").

Addthedistancefilledbythenewrowtotheamountofspace

filled.

Toggletheoffset(ifitiscentered,setitupoff-center,or

viceversa).

Gobacktothestartoftheloop.

Pleasesendusyourcommentaboutthispage

Page 125: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingtheTiles>AddingTilestotheGardenPath>

ApplyingSomeGeometry

Thereareonlyafewdimensionsyouneedtoknowtodrawthegardenpath.Thehalf-widthiseasy:itisjusthalfthewidthofthepath.Youalreadydefinedthecodetoobtainthiswidthfromusersandsaveditinanassociationlist.

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

Rowspacingisalittletrickier,unlessyouarereallysharpwithtrigonometry.Hereistheformula:

RowSpacing=(TileDiameter+SpacebetweenTiles)*(thesine

of60degrees)

Pleasesendusyourcommentaboutthispage

Page 126: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 127: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

(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 128: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

(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 129: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

(if(=offsetFromCenter0.0)

offsetDistance

0.0

)

)

Thisistheoffsettoggle,whichdetermineswhethertherowbeingdrawnshouldbeginwithacirclecenteredonthepathoroffsetfromthepath.Thepseudo-codeforthisalgorithmfollows:

Settheoffsetamounttothefollowing:

Iftheoffsetiscurrentlyzero,setittotheoffsetdistance;

Otherwise,setitbacktozero.

Pleasesendusyourcommentaboutthispage

Page 130: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 131: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Pleasesendusyourcommentaboutthispage

Page 132: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 133: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

(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 134: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

"\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 135: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 136: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>DrawingtheTiles>

WrappingUpLesson5

YoustartedthislessonbylearningVLISPeditingfeaturesthathelpedyou

Matchtheparenthesesinyourcode.

Findandcompleteafunctionname.

ObtaininformationinHelpforafunction.

Youfinishedthelessonbybuildingcodethatdrawsthetilesinthegardenpath.Younowhaveaprogramthatmeetstherequirementsestablishedattheverybeginningofthistutorial.

Atthispoint,youprobablyhaveacquiredenoughexperiencewithVLISPtoventureoffonyourown.Butifyouareuptoit,therearetwomorelessonsinthistutorialthatdemonstratetheuseofreactorfunctionsandotheradvancedfeaturesoftheVLISPenvironment.

Pleasesendusyourcommentaboutthispage

Page 137: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>

ActingwithReactors

Inthislesson,youwilllearnaboutreactorsandhowtoattachthemtodrawingeventsandentities.ReactorsallowyourapplicationtobenotifiedbyAutoCAD®

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

ReactorBasicsDesigningReactorsfortheGardenPathTestDrivingYourReactorsWrappingUpLesson6

Pleasesendusyourcommentaboutthispage

Page 138: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>ActingwithReactors>

ReactorBasics

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

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

ReactorTypes

Pleasesendusyourcommentaboutthispage

Page 139: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 140: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

thenwritethecallbackfunctionthatistriggeredwhentheeventoccurs.

Pleasesendusyourcommentaboutthispage

Page 141: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>ActingwithReactors>

DesigningReactorsfortheGardenPath

Toimplementreactorfunctionalityinthegardenpathapplication,startbyhandlingjustafewevents,ratherthantryingtocoverallpossibleuseractions.

SelectingReactorEventsfortheGardenPathPlanningtheCallbackFunctionsPlanningforMultipleReactorsAttachingtheReactorsStoringDatawithaReactorUpdatingtheC:GPathFunctionAddingReactorCallbackFunctionsCleaningUpAfterYourReactors

Pleasesendusyourcommentaboutthispage

Page 142: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>ActingwithReactors>DesigningReactorsfortheGardenPath>

SelectingReactorEventsfortheGardenPath

Forthetutorial,setthefollowinggoals:

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

Whenthegardenpathboundaryiserased,erasethetilesaswell.

Pleasesendusyourcommentaboutthispage

Page 143: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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

Page 144: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Erasethetiles

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 145: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 146: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the
Page 147: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 148: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 149: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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))

Page 150: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

);_endofgp:getDialogInput

);_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.

Page 151: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

(listPolylineName)

;;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)

Page 152: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

2. Reviewthecodemodificationsandcommentsdescribingwhateachnewstatementdoes.Thistutorialshowsallmodifiedcodeinboldface.

Pleasesendusyourcommentaboutthispage

Page 153: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 154: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 155: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 156: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

byclickingtoactivatetheVLISPwindow.Ifthishappens,simplyentervlispattheAutoCADCommandprompttoreturntoVLISP.

ExaminingReactorBehaviorinDetail

Pleasesendusyourcommentaboutthispage

Page 157: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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(viagrips)/Polylineborder(path9)

Stretch/Polylineborder(path10)

Thisexercisewillgiveyouagoodunderstandingofwhatishappeningbehindthescenes.AtanytimethroughoutLesson7whenthereactorfunctionality

Page 158: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

becomesconfusing,refertoyour“reactor-tracesheets.”

Pleasesendusyourcommentaboutthispage

Page 159: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>ActingwithReactors>

WrappingUpLesson6

Inthislesson,youwereintroducedtoAutoCADreactorsandhowtoimplementthemusingVLISP.Youdesignedaplanforaddingreactorstothegardenpathapplication,andaddedsomeofthecodeyourprogramwillneedtoimplementtheplan.

Reactorscanaddagreatdealoffunctionalitytoanapplication,butremember—themorepowerfulyourprogramscanbe,thehardertheycancrash.

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

Pleasesendusyourcommentaboutthispage

Page 160: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>

PuttingItAllTogether

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

Youshouldconsiderthispartofthetutorialastheadvancedtopicssection.Ifyouareabeginner,youmaynotunderstandalltheAutoLISP®codepresentedhere.ThereareseveralAutoLISPbookslistedattheendofthislessonthatprovidemorethoroughinformationonsomeoftheadvancedAutoLISPconceptspresentedhere.

PlanningtheOverallReactorProcessAddingtheNewReactorFunctionalityRedefiningthePolylineBoundaryWrappingUptheCodeBuildinganApplicationWrappingUptheTutorialLISPandAutoLISPBooks

Pleasesendusyourcommentaboutthispage

Page 161: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 162: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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 163: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

pointer.

AutoCADdeletesthepolylines.

Yourcallbackfunctiongp:command-endedfires.Eliminateanytilesassociatedwiththereactorpointersstoredin*reactorsToRemove*.

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

ReactingtoMoreUser-InvokedCommandsStoringInformationWithintheReactorObjects

Pleasesendusyourcommentaboutthispage

Page 164: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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,then

Page 165: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

redrawninthenewlocation.Thisisafairlysimpleoperation,becausethepolylineboundarydidnotchangeitssizeorshape.

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 166: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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.

Page 167: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Assemblingtheperimeterpointlistsissimple.Lookatthecodeingp: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)

Page 168: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

poly2Dpoints(apply'append

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

)

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. AddPolylineListtothelocalvariablessectionofthe

Page 169: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

C:GPathfunctiondefinition.

Pleasesendusyourcommentaboutthispage

Page 170: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 171: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

associativitybetweenthetilesandthepath.Iftheuserissuedsuchacommand,theprogramsetsthe*lostAssociativity*globalvariableandwarnstheuser.Asyouexperimentwiththegardenpathapplication,youmaydiscoveradditionaleditingcommandsthatcanmodifythegardenpathandcausethelossofassociativity.Addthesecommandstothequotedlistsothattheuserisawareofwhatwillhappen.Whenthisfunctionfires,theuserhasstartedacommandbuthasnotselectedanyentitiestomodify.Theusercouldstillcancelthecommand,leavingthingsunchanged.AddingActivitytotheObjectReactorCallbackFunctionsDesigningthegp:command-endedCallbackFunctionHandlingMultipleEntityTypesUsingActiveXMethodsinReactorCallbackFunctionsHandlingNonlinearReactorSequencesCodingthecommand-endedFunctionUpdatinggp:Calculate-and-Draw-TilesModifyingOtherCallstogp:Calculate-and-Draw-Tiles

Pleasesendusyourcommentaboutthispage

Page 172: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 173: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

)

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

Pleasesendusyourcommentaboutthispage

Page 174: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 175: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Pleasesendusyourcommentaboutthispage

Page 176: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 177: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>PuttingItAllTogether>AddingtheNewReactorFunctionality>

UsingActiveXMethodsinReactorCallbackFunctions

Theseconddetailappearinginthepseudo-codeshowsupneartheend,atthestepforredrawingthetiles.Hereisthepseudo-codestatement:

Redrawthetiles(forceActiveXdrawing)

Theparentheticalphrasesaysitall:forceActiveXdrawing.Whyisthisrequired?Whycan'ttheapplicationusetheobjectcreationpreferencestoredintheassociationsublist?

Theanswerisyoucannotusethecommandfunctionforentitycreationwithinareactorcallbackfunction.ThishastodowithsomeinternalworkingsofAutoCAD.YouneedtoforcethetiledrawingroutinetouseActiveX.Youwillhearmoreaboutthisissuelaterinthislesson.

Pleasesendusyourcommentaboutthispage

Page 178: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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,youcan

Page 179: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

useanotherglobalvariabletostorealistofpointerstothetileobjectsuntiltheycanbedeleted.

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 180: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

)

)

(setq*Safe-to-Delete*nil)

)

)

)

ThisfunctioncanbeinvokedatatimewhenaGRIP_MOVEorGRIP_STRETCHcommandisnotbeingexecuted.

Pleasesendusyourcommentaboutthispage

Page 181: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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

Page 182: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

;;performedonasinglePOLYLINEatatime.

((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))

)

)

Page 183: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

;;...updatetheoutlineofthepolylinewiththenewpoints

;;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

Page 184: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

*reactorsToChange*nil

)

)

)

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

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

(princ)

)

Pleasesendusyourcommentaboutthispage

Page 185: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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,and

Page 186: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

ObjectCreationStyleisidentifiedasalocalvariable.ReviewhowtheObjectCreationStylevariableisset,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))

Page 187: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

TileRadius(cdr(assoc42BoundaryData))

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 188: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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.

Page 189: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Whenyouselectthisoption,theFinddialogboxexpandsatthebottom,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

Page 190: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

(gp:RedefinePolyBorderCurrentPointsreactorData)

);_endofsetq

Pleasesendusyourcommentaboutthispage

Page 191: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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.LookingattheFunctionsingppoly.lspUnderstandingthegp:RedefinePolyBorderFunctionUnderstandingthegp:FindMovedPointFunctionUnderstandingthegp:FindPointInListFunctionUnderstandingthegp:recalcPolyCornersFunctionUnderstandingthegp:pointEqual,gp:rtos2,andgp:zeroSmallNumFunctions

Pleasesendusyourcommentaboutthispage

Page 192: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 193: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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

Pleasesendusyourcommentaboutthispage

Page 194: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 195: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 196: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 197: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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 198: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

Withthisknowledge,seeifthegp:FindPointInListfunctionmakessense.Again,reviewthecommentswithinthesourcecode.

Pleasesendusyourcommentaboutthispage

Page 199: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>PuttingItAllTogether>RedefiningthePolylineBoundary>

Understandingthegp:recalcPolyCornersFunction

Thekeytounderstandinghowgp:recalcPolyCornersworksistorevisitthediagramshowingwhatthekeyvaluesof12through15represent:

Inthediagram,theusermovedthecornerpointassociatedwiththekeyvalueof14.Thismeansthecornerpointsassociatedwith13and15needtoberecalculated.

Point15needstobemovedalongthecurrentvectordefinedbypoint12topoint15untilitlinesupwiththenewpoint14.Thevectorsfrom12to15,andfrom14to15,mustbeperpendiculartoeachother.Thesameoperationmustbeappliedtorecalculatethenewlocationforpoint13.

Nowtakeanotherlookatthecodetoseeifitmakessense.

Pleasesendusyourcommentaboutthispage

Page 200: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 201: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 202: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>PuttingItAllTogether>

BuildinganApplication

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

Note Itisrecommendedthatyouproceedwithbuildinganapplicationonlyifyourcodeisingoodworkingform.Makesurethatyouhavetestedyourapplicationusingtheoriginalsourcefiles,andthatyouaresatisfiedwiththeresults.

StartingtheMakeApplicationWizard

Pleasesendusyourcommentaboutthispage

Page 203: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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 204: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

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 205: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>PuttingItAllTogether>

WrappingUptheTutorial

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

Pleasesendusyourcommentaboutthispage

Page 206: AutoLISP Tutorial > Introduction · AutoLISP Tutorial > Designing and Beginning the Program In this first lesson, you'll begin by defining what the application will do. Using the

AutoLISPTutorial>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