JimYuan's Blog

Sharing the things I learned

0%

Preface

It’s been a while that I updated my blog, and it’s about time. I spent some time learning Three.js recently. Before this, I only know basic html, css and javascript. Though some people might think that’s totally enough for being a front-end developer in the old days, there’s tons of great tools I needed to catch up with. I think I will catch up through doing some side projects.

To name a few, which at this point, I think I should definitely check them out in near future.

  • TypeScript
  • React
  • Webpack

FrontEnd - Roadmap

By a quick google search,
https://roadmap.sh/frontend

Though I am not sure if I will end up being a front-end developer, I want to put AEC models on web, so it kinda means I have to learn these…
I’ll do my best.

First Person Shooter

https://en.wikipedia.org/wiki/First-person_shooter

Basically, I was following this tutorial.
https://www.youtube.com/watch?v=Q_I0Tq61Ud8&t=744s

So, yeah.

The key ideas is to combine thess two parts.

  • PointerLockContorls
  • wasd control

https://threejs.org/docs/#examples/en/controls/PointerLockControls


PointerLockContorls

1
2
3
4
5
6
7
8
import {
PointerLockControls
} from "three/examples/jsm/controls/PointerLockControls"

const controls = new PointerLockControls(camera, document.domElement);
window.addEventListener("click", () => {
controls.lock();
});

wasd contorls

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//前進か後進か変数宣言
let moveForward = false;
let moveBackward = false;
let moveLeft = false;
let moveRight = false;

//移動速度と移動方向の定義
const velocity = new THREE.Vector3();
const direction = new THREE.Vector3();



const onKeyDown = (e) => {
switch (e.code) {
case "KeyW":
moveForward = true;
console.log(moveForward)
break;
case "KeyS":
moveBackward = true;
break;
case "KeyA":
moveLeft = true;
break;
case "KeyD":
moveRight = true;
break;
}
};

const onKeyUp = (e) => {
switch (e.code) {
case "KeyW":
moveForward = false;
console.log(moveForward)
break;
case "KeyS":
moveBackward = false;
break;
case "KeyA":
moveLeft = false;
break;
case "KeyD":
moveRight = false;
break;
}
};


document.addEventListener("keydown", onKeyDown);
document.addEventListener("keyup", onKeyUp);

let prevTime = performance.now();


function animate() {
requestAnimationFrame(animate);

const time = performance.now();


// 前進後進判定
direction.z = Number(moveForward) - Number(moveBackward);
direction.x = Number(moveLeft) - Number(moveRight);


//ポインターがONになったら
if (controls.isLocked) {
const delta = (time - prevTime) / 1000;

// decline
velocity.z -= velocity.z * 5.0 * delta;
velocity.x -= velocity.x * 5.0 * delta;

if (moveForward || moveBackward) {
velocity.z -= direction.z * 200 * delta;
}

if (moveRight || moveLeft) {
velocity.x -= direction.x * 200 * delta;
}



controls.moveForward(-velocity.z * delta);
controls.moveRight(-velocity.x * delta);
}
prevTime = time;
renderer.render(scene, camera);
}

animate();

Preface

I have absolutely zero idea of the openCV library before watching this tutorial. I hope I can take away some useful knowledge by noting down some code here.

Reference

youtube
github

Reading Image and Video

Read Image

1
2
3
4
5
6
import cv2 as cv

img = cv.imread('../Resources/Photos/cats.jpg')
cv.imshow('Cats', img)

cv.waitKey(0)

Read Video

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
capture = cv.VideoCapture('../Resources/Videos/dog.mp4')

while True:
isTrue, frame = capture.read()

# if cv.waitKey(20) & 0xFF==ord('d'):
# This is the preferred way - if `isTrue` is false (the frame could
# not be read, or we're at the end of the video), we immediately
# break from the loop.
if isTrue:
cv.imshow('Video', frame)
if cv.waitKey(20) & 0xFF==ord('d'):
break
else:
break

capture.release()
cv.destroyAllWindows()

Resizing and Rescaling

We often resize and rescale the image to relieve the computational strain.

Drawing Shapes and Putting Texts

5 Essential Function in OpenCV

  • Converting to grayScale
  • Blur
  • Edge Cascade
  • Dilating the image
  • Eroding
  • Resize

Converting to grayScale

1
gray = cv.cvtColor(img, cv.COLOR2GRAY)

Blur

1
blur = cv.GussianBlur(img, (7,7), cv.BORDER_DEFAULT)

Edge Cascade

1
2
canny = cv.Canny(img, 125, 175,)
canny = cv.Canny(cv.GussianBlur(img, (7,7), cv.BORDER_DEFAULT, 125,175) # passing blur image

Dilating the image

1
dilated = cv.dilated(canny, (3,3), iteration=1)

Eroding

1
eroded = cv.erode(dilated, (3,3), iteration=3)

Resize

1
resized = cv.resized(img, (500, 500), interpolation=cv.INTER_CUBIC)

Cropping

1
cropped = img[50:200, 200:400]

Image Transformation

  • Translation
  • Rotation
  • Resizing
  • Flipping
  • Cropping

Contour detection

Preface

In grasshopper, there’s one component called shift_list and basically it did things like Rotate_Array. People can plug in one number and make the list shift/rotate with that number.
Recently, I am trying to catch up some algorithms from Leetcode, and Rotate_Array is one of them.


Example:
Input:
[1,2,3,4,5]
3

Output:
[4,5,1,2,3]


There are obviously some solution for this question. The one I am looking for is the one can acchieve in_place property.

1
2
3
4
5
6
7
8
public:
void rotate(vector<int>& nums, int k) {
k %= nums.size();
reverse(nums.begin(),nums.end());
reverse(nums.begin(),nums.begin()+k);
reverse(nums.begin()+k,nums.end());
}
};

Reference

https://leetcode.com/problems/rotate-array/
https://www.geeksforgeeks.org/array-rotation/
https://leetcode.com/problems/rotate-array/discuss/1729976/C%2B%2B-or-O(N)-or-GCD

Preface

Happy new year, it’s 2022 now. It’s been a while since the last time I updated my blog. Though I didn’t write something in a quite long period of time, I still check some interesting fellows’ work. There’s an open source project from Arup was released on github, so I decided to give it a look.

Reference

https://github.com/arup-group/Custom-Grasshopper-UI-Components

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
using Grasshopper.Kernel;
using Rhino.Geometry;
using System;
using System.Collections.Generic;

// In order to load the result of this wizard, you will also need to
// add the output bin/ folder of this project to the list of loaded
// folder in Grasshopper.
// You can use the _GrasshopperDeveloperSettings Rhino command for that.

namespace CustomGhComponents
{
public class ComponentWithDropDown : GH_Component
{
/// <summary>
/// Each implementation of GH_Component must provide a public
/// constructor without any arguments.
/// Category represents the Tab in which the component will appear,
/// Subcategory the panel. If you use non-existing tab or panel names,
/// new tabs/panels will automatically be created.
/// </summary>
public ComponentWithDropDown()
: base("DropDownComponent", "DropDown",
"A component with dropdown menus",
"Category", "Subcategory")
{
}

//This region overrides the typical component layout
public override void CreateAttributes()
{
if (first)
{
FunctionToSetSelectedContent(0, 0);
first = false;
}
m_attributes = new CustomUI.DropDownUIAttributes(this, FunctionToSetSelectedContent, dropdowncontents, selections, spacerDescriptionText);
}

public void FunctionToSetSelectedContent(int dropdownListId, int selectedItemId)
{
// on first run we create the combined dropdown content
if (dropdowncontents == null)
{
// create list to populate dropdown content with
dropdowncontents = new List<List<string>>(); //clear all previous content
selections = new List<string>();

dropdowncontents.Add(dropdownTopLevelContent); //add Top Level content as first list
selections.Add(dropdownTopLevelContent[0]);

dropdowncontents.Add(dropdownLevel2_A_Content); //add level 2 first list as default on first run
selections.Add(dropdownLevel2_A_Content[0]);

// add the lists corrosponding to top level content order
dropdownLevel2_Content.Add(dropdownLevel2_A_Content);
dropdownLevel2_Content.Add(dropdownLevel2_B_Content);
dropdownLevel2_Content.Add(dropdownLevel2_C_Content);
dropdownLevel2_Content.Add(dropdownLevel2_D_Content);
}

if (dropdownListId == 0) // if change is made to first list
{
// change the content of level 2 based on selection
dropdowncontents[1] = dropdownLevel2_Content[selectedItemId];

// update the shown selected to first item in list
selections[1] = dropdowncontents[1][0];
}

if (dropdownListId == 1) // if change is made to second list
{
selections[1] = dropdowncontents[1][selectedItemId];

// do something with the selected item
System.Windows.Forms.MessageBox.Show("You selected: " + dropdowncontents[1][selectedItemId]);
}

// for Grasshopper to redraw the component to get changes to dropdown menu displayed on canvas:
Params.OnParametersChanged();
ExpireSolution(true);
}

#region dropdownmenu content
// this region is where (static) lists are created that will be displayed
// in the dropdown menus dependent on user selection.

List<List<string>> dropdowncontents; // list that holds all dropdown contents
List<List<string>> dropdownLevel2_Content = new List<List<string>>(); // list to hold level2 content

List<string> selections; // list of the selected items
bool first = true; // bool to create menu first time the component runs

readonly List<string> spacerDescriptionText = new List<string>(new string[]
{
"TopLevel List",
"Level2 Items"
});
readonly List<string> dropdownTopLevelContent = new List<string>(new string[]
{
"ListA",
"ListB",
"ListC",
"ListD"
});
// lists longer than 10 will automatically get a vertical scroll bar
readonly List<string> dropdownLevel2_A_Content = new List<string>(new string[]
{
"Item A1",
"Item A2",
"Item A3",
"Item A4",
"Item A5",
"Item A6",
"Item A7",
"Item A8",
"Item A9",
"Item A10",
"Item A11",
"Item A12",
"Item A13",
});

readonly List<string> dropdownLevel2_B_Content = new List<string>(new string[]
{
"Item B1",
"Item B2",
"Item B3",
"Item B4",
"Item B5",
"Item B6",
"Item B7",
"Item B8",
"Item B9",
});

readonly List<string> dropdownLevel2_C_Content = new List<string>(new string[]
{
"Item C1",
"Item C2",
"Item C3",
"Item C4",
"Item C5",
"Item C6",
"Item C7",
"Item C8",
"Item C9",
"Item C10",
"Item C11",
"Item C12",
"Item C13",
"Item C14",
"Item C15",
"Item C16",
});

readonly List<string> dropdownLevel2_D_Content = new List<string>(new string[]
{
"Item D1",
"Item D2",
"Item D3",
"Item D4",
"Item D5",
"Item D6",
});
#endregion

/// <summary>
/// Registers all the input parameters for this component.
/// </summary>
protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
{
pManager.AddGenericParameter("Input1", "I1", "First Input", GH_ParamAccess.item);
pManager[0].Optional = true;
}

/// <summary>
/// Registers all the output parameters for this component.
/// </summary>
protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
{
pManager.AddGenericParameter("Output1", "O1", "First Output", GH_ParamAccess.item);
}

/// <summary>
/// This is the method that actually does the work.
/// </summary>
/// <param name="DA">The DA object can be used to retrieve data from input parameters and
/// to store data in output parameters.</param>
protected override void SolveInstance(IGH_DataAccess DA)
{
// set output to selected
DA.SetData(0, selections[1]);
}

/// <summary>
/// Provides an Icon for every component that will be visible in the User Interface.
/// Icons need to be 24x24 pixels.
/// </summary>
protected override System.Drawing.Bitmap Icon
{
get
{
// You can add image files to your project resources and access them like this:
//return Resources.IconForThisComponent;
return null;
}
}

/// <summary>
/// Each component must have a unique Guid to identify it.
/// It is vital this Guid doesn't change otherwise old ghx files
/// that use the old ID will partially fail during loading.
/// </summary>
public override Guid ComponentGuid
{
get { return new Guid("020959db-8b03-4a62-9a25-5b34e4e44812"); }
}
}
}

Skills

THIS PAGE IS NOT YET FINISHED

Preface

Apparently, we can develop APIs with LISP and .NET . Though I have been checking some articles mentioning the pros and cons for using one another, it is still unclear to me, which scenario suit for which development method. I think I might realize the answer of this question along my development journey. Few weeks ago, I learned some basic LISP, but the materials that I checked wasn’t completed. LISP is the second oldest programming language that still exist, which make the programmer like me a bit hard to catch up easily. Since I spent more time developing in C#, it won’t hurt if I learn a bit how to develop AutoCAD API in .NET framework.

DLLs

  • ACMGD.DLL
  • ACDBGD.DLL
  • ACCOREMGD.DLL

using lines

1
2
3
4
5
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;

Workflow

  1. Create the Class Library(.NET framework)
  2. Add those 3 dlls listed above
  3. Add the using lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;

namespace DrawObject{
public class DrawObject{
[CommandMethod("DrawLine")]
public void DrawLine(){

}
}

}

Reference

https://amdlaboratory.com/amdblog/autocad%E3%81%AEaddin%E3%82%92c%E3%81%A7%E4%BD%9C%E3%82%8B%E6%96%B9%E6%B3%95/

Reference

Binary_Heap

Binary Heap

A Binary Heap is a Binary Tree with following properties.

  • It’s a complete tree. This property makes them suitable to be stored in an array
  • A Binary Heap is either Min Heap or Max Heap. (Recursively)

How is Binary Heap represent?

A Binary Heap is a Complete Binary Tree. A binary heap is typically represented as an array.

  • The root element will be at Arr[0]

  • Arr[(i-1)/2] : the parent node

  • Arr[(2*i)+1] : the left child

  • Arr[(2*i)+2] : the right child

Applications of Heaps:

  1. Heap Sort: Heap Sort uses Binary Heap to sort an array in O(nLogn) time.
  2. Priority Queue: Priority queues can be efficiently implemented using Binary Heap because it supports insert(), delete() and extractmax(), decreaseKey() operation in O(logn) time.
  3. Graph Algorithms: The priority queues are especially used in Graph Algorithms like Dijkstra's Shortest Path and Prim's Minimum Spanning Tree
  4. Many problems can be efficiently solved using Heaps. See following. for example.
    1. K’th Largest Element in an array
    2. Sort an almost sorted array
    3. Merge K sorted Arrays

Operation on Min Heap

  1. getMini()
  2. extractMin()
  3. decreaseKey()
  4. insert()
  5. delete()

Reference

  • entsel : prompts the user to select a single object(entity) by specifying a point
  • car
  • cdr
  • entget

entsel

1
(setq en1 (entsel))

If you want to prompt user with a sentence

1
(setq e (entsel "Please choose an object: "))

More about entsel

Return value:

A list whose first element is the entity name of the chosen object and whose second element is the coordinates (in terms of the current UCS) of the point used to pick the object.

The pick point returned by entsel does not represent a point that lies on the selected object.

car

1
(car en1)

In the previos example, (car en1) here will return the first element in the list, which is the EntityName

cadr

1
(cadr en1)

In the previos example, (car en1) here will return the second element in the list, which is the point location

entget

Retrieves an object’s (entity’s) definition data

1
(setq en1_data (entget (car en1)))

If the entity you selected is in the different types, entget may return different geometry infomation.

群碼分析表

Group Codes by Name

If the graph info pair separated by ., (1 . “ABC”) for example, we need to use cdr to retrieve the secend element, instead of cadr

1
(cons 1 "ABC")

can create an dot pair, (1 . “ABC”)

How to revise the data?

  1. entget to get the entity information

  2. assoc to find the correct group_code string pair. The new string pair can be created by cons

  3. subst to swap/change the new/old string pairs

  4. entmod to renew the autocad canvas and show the new string pair

  5. !ent_data

  6. (setq oldr (assoc 40 en1_data))

  7. (setq newr (cons 40 23.8))

  8. (setq en1_data (subst newr oldr en1_data))

  9. (entmod en1_data)

  • entget
  • assoc: Searches an association list for an element and returns that association list entry
  • subst: Searches a list for an old item and returns a copy of the list with a new item substituted in place of every occurrence of the old
  • entmod

Differentiating Between Local and Global Variable

  • Global variables are accessible by all functions loaded within a document(or drawing).
  • Local variables retain their value only as long as the function that defined them is running. After the function finishes running, the local variable values are automatically discarded, and the system reclaims the memory space the variable used.

Using Local Variable in the Program

1
2
3
4
5
6
7
8
9
(defun gp:getPointInput	(/ StartPt EndPt HalfWidth)
(if (setq StartPt (getpoint "\nStart point of path: "))
(if (setq EndPt (getpoint StartPt "\nEndpoint of path: "))
(if (setq HalfWidth (getdist EndPt "\nhalf-width of path: "))
T
)
)
)
)

The local variables are declared following the slash character.


Tutorial: Garden Path (Visual LISP IDE)

Reference

  • The Visual LISP® environment is introduced.
  • ActiveX® and Reactor functions of AutoLISP are demonstrated, as well as several other extensions to the AutoLISP language provided with Visual LISP.

There are two possible executino contexts for this tutorial:

  • The application may be run as interpreted LISP in piecemeal files and/ or functions that are loaded into a single document.
  • Or, the program code can be compiled into a VLX application, denoted by a *.vlx executable. A VLX operates from a self-contained namespace that can interact with the application-loading document.

Lesson 1: Designing and Beginning the Program(Visual LISP IDE)

Reference

Defining Overall Program Goals

Task

  • Given a start point, an endpoint, and a width, draw a rectilinear boundary. The boundary can be at any 2D orientation. There should be no limit on how large or small it can be.
  • Prompt the user for tile size and tile spacing values. The tiles are simple circles and will fill the boundary but must not overlap or cross the boundary.
  • Place the tiles in alternating rows.

Example Location can be found in:
C:\Program Files\Autodesk\AutoCAD 2022\Tutorial\VisualLISP

Getting Started With Visual LISP

First, it helps to demonstrate what can happen when Visual LISP is waiting for contorl to return from AutoCAD.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
;;; Function C:GPath is the main program function and defines the 
;;; AutoCAD GPATH command.
(defun C:GPath ()
;; Ask the user for input: first for path location and
;; direction, then for path parameters. Continue only if you have
;; valid input.
(if (gp:getPointInput) ;
(if (gp:getDialogInput)
(progn
;; At this point, you have valid input from the user.
;; Draw the outline, storing the resulting polyline
;; "pointer" in the variable called PolylineName.
(setq PolylineName (gp:drawOutline))
(princ "\nThe gp:drawOutline function returned <")
(princ PolylineName)
(princ ">")
(Alert "Congratulations - your program is complete!")
)
(princ "\nFunction cancelled.")
)
(princ "\nIncomplete information to draw a boundary.")
)
(princ) ; exit quietly
)
;;; Display a message to let the user know the command name.
(princ "\nType gpath to draw a garden path.")
(princ)
  • defun: declare the funcation
  • C:GPath : Command, and the name is GPath
  • gp:getPointInput and getDialogInput: These function names are prefixed with gp: to indicate they are specific to the graden path applcation. This is not a requiremnet
  • The final princ without a string argument forces the program to exit quietly.

Filling the Gaps in the program

  • pg:getPointInput
  • pg:getUserInput
  • gp:drawOutline
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
;;; Function gp:getPointInput will get path location and size
(defun gp:getPointInput ()
(alert
"Function gp:getPointInput will get user drawing input"
)
;; For now, return T, as if the function worked correctly.
T
)
;;; Function gp:getDialogInput will get path parameters
(defun gp:getDialogInput ()
(alert
"Function gp:getDialogInput will get user choices through a dialog"
)
;;For now, return T, as if the function worked correctly.
T
)
;;; Function gp:drawOutline will draw the path boundary
(defun gp:drawOutline ()
(alert
(strcat "This function will draw the outline of the polyline"
"\nand return a polyline entity name/pointer."
)
)
;; For now, simply return a quoted symbol. Eventually, this
;; function will return an entity name or pointer.
'SomeEname
)
  • The letter T is the symbol for “true” in AutoLISP
  • The way gpmain.lsp is structured, each input function it calls must return a value other than nil(no value) for the program to proceed to the next step.

An AutoLISP function will, by default, return the value of the last expression evaluated within it. In the stubbed-out functions, the only expression is a call to the alert function. But alert always returns nil. If this is left as the last expression in gp:getPointInput, it will always return nil, and you will never pass through the if to the gp:getDialogInput function.

For a similar reason, the end of the gp:DrawOutline function returns a quoted symbol (‘SomeEname) as a placeholder. A quoted symbol is a LISP construct that is not evaluated. (If you are curious about how the LISP language works, there are a number of good books available, mentioned at the end of this tutorial.)

Reference

https://help.autodesk.com/cloudhelp/2018/CHS/AutoCAD-AutoLISP-Tutorials/files/index.htm#!

Basic Tutorial

Tutoiral: Getting Started(AutoLISP)

Autodesk explanation Link

AutoLISP is based on the LISP(LISt Processing) programming
langauage.

A list is a structure enclosed by parentheses.

Usually, the first element in the list is the name of a function, and the following elements are called arguments.

1
(function_name [argument1 argumentX ...])

The ! (exclamation point) character can only be used at the AutoCAD Command prompt and is used to return the current value of an AutoLISP variable.


1
(+ 0.01 (* 2 0.875))
  • 2 * 0.875 = 1.75
  • 0.01 + 1.75 = 1.76

1
(setq nDist (getreal "\nEnter a distance: "))

The getreal function prompts the user for a real numeric value. The value provided is then passed to the setq function and assigned to the nDist user-defined variable.


1
(alert (strcat "Welcome" "to" "AutoLISP!"))

The stract function combines all the strings into a single string value. The value returned bt the strcat function is then passed to the alert function and displayed in a message box.

Tutoiral: Creating a New Custom Command and Controllign wiht System Variables(AutoLISP)

Your custom commands can use standard AutoCAD commands with the command function, or they can directly manipulate objects using AutoLISP functions.

Creating a New Function

defun means “define function.”

1
(defun function_name ([arguments] [/ local_variables ...]) expr ...)

The defun function also allows you to define a list of arguments that can be passed to the function and a list of user-defined variable that are “local” to the function.

1
2
3
4
5
6
7
(defun display-msg (msg mode / )
(if (= mode 0)
(prompt (strcat "\n" msg))
(alert msg)
)
(princ)
)
  • (display-msg “Hello from AutoLISP!” 0)
  • (display-msg “Hello from AutoLISP!” 1)

Creating a Custom Command

A custom command is a function that is defined with the defun function, but uses a special naming convention: they use the characters c: as a prefix. This distinguishes them from other functions.

You can define a function that accepts arguments, but you should never define a function that will be used as a custom command to accpet arguments.

1
2
3
4
(defun c:hello ( / msg)
(setq msg (getstring T "\nEnter a message: "))
(alert msg)
)

msg is a varible only exist inside the c:hello scope.

You can save your AutoLISP expressions to a file with the LSP file extension so they can be reused and loaded into other drawings.

Accessing and Setting System Variable Value

Getter/ Setter

  • getvar: Returns the current value of a system variable
  • setvar: Assigns a new value to a system variable

The following explain how to get and set the value of the OSMODE(Object Snap Mode) system varible.

  1. At the Command prompt, enter (setq cur_osmode (getvar “osmode”))
    The current value of the OSMODE system variable is returned and assigned to the user-defined variable of cur_osmode. While OSMODE returns an integer value, the value is the sum of multiple “bit-code“ values. For example, the value 35 indicates that the EndPoint(1), Midpoint(2) and Intersection(32) running object snaps are enabled.
  2. At the Command prompt, enter osnap

Creating, Loading, and Opening an AutoLISP File(AutoLISP)

AutoLISP is an interpretive language, so it can be stored in an ASCII text file, loaded, and then executed directly within AutoCAD.

AutoLISP files typically have an .lsp file extension, but they can also have the .mnl file extension. Both LSP and MNL files can be edited with a text editor.

MNL files are associated with user interface customization and they are automatically loaded into AutoCAD when a customization (CUI/ CUIx) file of the same name is loaded. For example, the acad.mnl is automatically loaded into AutoCAD when the acad.cuix file is loaded.

We can open any text editor create and .lsp file and load it into AutoCAD.

The way to load it into AutoCAD.

  • Manage > Application> Load Application(Find the correct file)