-
Notifications
You must be signed in to change notification settings - Fork 0
Spine
๋ณธ ๋ฌธ์๋ ๋ก๋ด ๋๋ก์ ์์คํ
Plotto์ Spine.js ํ์ผ์ ์ค๋ช
ํฉ๋๋ค.
์ด ๋ฌธ์๋ Plotto ๋ก๋ด ํ ์ฝ๋์ ๊ตฌ์ฑ ์์์ ์๋ ๋ฐฉ์์ ์ค๋ช
ํฉ๋๋ค. ํด๋น ์ฝ๋๋ 2์์ ๋(2-DOF) ๋ก๋ด ํ์ ์ ์ดํ์ฌ SVG๋ก ์ ์๋ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ํ์ผ๋ก ๊ทธ๋ฆผ์ ๊ทธ๋ฆฌ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค. ์ฝ๋์ ์ฃผ์ ์์, ํด๋์ค ์์ฑ, ํจ์, ๊ทธ๋ฆฌ๊ณ ์ ์ฒด์ ์ธ ๋์ ํ๋ฆ์ ๋จ๊ณ์ ์ผ๋ก ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์์ธํ ๋ณด๊ธฐ
์ฝ๋ ์๋จ์๋ ๋ก๋ด ํ์ ๋ฌผ๋ฆฌ์ ์ธ ์น์์ ์ด๊ธฐ ์ํ๋ฅผ ๋ํ๋ด๋ ์์๋ค์ด ์ ์๋์ด ์์ต๋๋ค. ์์ธํ ์ค๋ช ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
-
TOP_JOINT๋ก๋ด ํ ์๋ถ ๊ด์ ์ ์ด๋ฏธ์ง ์ขํ์ ๋๋ค.
const TOP_JOINT_X = 220; const TOP_JOINT_Y = 547;
-
UPPER_JOINT_BASE๋ก๋ด ํ ์๋ถ ์(upper arm)์ด ๊ธฐ์ค(base)์ ๋ถ์ฐฉ๋ ์ง์ ์ ์ด๋ฏธ์ง ์ขํ์ ๋๋ค. ์๋ถ ์์ ์์์ ์ด๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค.
const UPPER_JOINT_BASE_X = 747; const UPPER_JOINT_BASE_Y = 226;
-
UPPER_JOINT_ELBOW: ์ ์์ ์์์ (ํ๊ฟ์น)์ ์ด๋ฏธ์ง ์ขํ์ ๋๋ค. ์ด์์ ์ผ๋ก๋ UPPER_JOINT_ELBOW์ ๋์ผํ ์์น์ฌ์ผ ํ์ง๋ง, ์ธก์ ์ค์ฐจ๋ก ์ฝ๊ฐ ์ฐจ์ด๊ฐ ์์ ์ ์์ต๋๋ค.
const UPPER_JOINT_ELBOW_X = 195; const UPPER_JOINT_ELBOW_Y = 383;
-
FORE_JOINT_ELBOW์ ์์ ์์์ (ํ๊ฟ์น)์ ์ด๋ฏธ์ง ์ขํ์ ๋๋ค. ์ด์์ ์ผ๋ก๋ UPPER_JOINT_ELBOW์ ๋์ผํ ์์น์ฌ์ผ ํ์ง๋ง, ์ธก์ ์ค์ฐจ๋ก ์ฝ๊ฐ ์ฐจ์ด๊ฐ ์์ ์ ์์ต๋๋ค.
const FORE_JOINT_ELBOW_X = 195; const FORE_JOINT_ELBOW_Y = 385;
-
FORE_PEN๋ก๋ด ํ ๋์ ๋ถ์ฐฉ๋ ํ(Pen) ๋์ ์ ์ด๋ฏธ์ง ์ขํ์ ๋๋ค. ์ ์์ ๋์ (ํ์ด ์์นํ ์ง์ )์ ๋ํ๋ ๋๋ค.
const FORE_PEN_X = 778; const FORE_PEN_Y = 612;
-
imageScale์ด๋ฏธ์ง ์ขํ๋ฅผ ์ค์ ๋ก๋ด์ ๊ธธ์ด ๋จ์๋ก ๋ณํํ๊ธฐ ์ํ ์ค์ผ์ผ ๊ณ์์ ๋๋ค.
์)
const imageScale = 0.5;: ์ด๋ฏธ์ง ๊ธธ์ด๋ฅผ ์ ๋ฐ ์ค์ผ์ผ ํ ์ค์ ๊ธธ์ด๋ก ์ฌ์ฉํฉ๋๋ค.
์ด ๊ฐ๋ค์ ๋ก๋ด ํ์ ๊ธฐ๊ตฌํ์ ํน์ฑ์ ์ค์ ํ๊ณ , ์ด๋ฏธ์ง ๋๋ ์ค๊ณ๋์์ ์ธก์ ๋ ์ขํ๋ฅผ ์ฌ์ฉํ์ฌ ๋ก๋ด ํ์ ๊ธธ์ด์ ๊ฐ๋๋ฅผ ๊ณ์ฐํ๋ ๋ฐ ํ์ฉ๋ฉ๋๋ค. ๋ค์์ผ๋ก ์ฃผ์ Plotto์ ํด๋์ค๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๋ชจ๋ ๋ณ์๋ getter / setter๊ฐ ์ ์๋์ด ์์ต๋๋ค.
๋ก๋ดํ ๊ธฐ์ค ์ขํ์ ๋๋ค. joint1์ ๋ชจํฐ ๋ถ๋ถ์ด ์์นํ๋ ์ขํ๋ฅผ ๋ํ๋ ๋๋ค.
๋ก๋ด ํ์ ๋ ๊ด์ ์ฌ์ด ๊ธธ์ด๋ฅผ ๋ํ๋ ๋๋ค. #link1์ ์๋ถ ํ(joint1 ~ joint2)์ ๊ธธ์ด, #link2๋ ํ๋ถ ํ(joint2 ~ pen)์ ๊ธธ์ด์ ๋๋ค. ์ด ๊ฐ๋ค์ initLinkGeometry()ํจ์์์ ๊ณ์ฐ๋ฉ๋๋ค.
๋ก๋ดํ์ด ๊ธฐ์ค ์์ธ์ ์ด๋ฏธ์ง ๊ฐ๋๋ฅผ ๋ผ๋์ ๊ฐ์ผ๋ก ๋ณํํ ๊ฐ ์ ๋๋ค. upperRestAngle์ ์๋ถ ํ์ ์ด๋ฏธ์ง ๊ฐ๋ ์ ๋๋ค, foreRestAngle์ ํ๋ถ ํ์ ์ด๋ฏธ์ง ๊ฐ๋ ์ ๋๋ค. ์ด ๋ ๊ฐ๋๋ ์ / ์ญ ๊ธฐ๊ตฌํ ๊ณ์ฐ์ ๋ณด์ ๊ฐ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
๋๋ฒ์งธ ๊ด์ ์ ์คํ์ ๊ฐ๋(offset)์ ๋๋ค. ์ด ๊ฐ์ ๋ก๋ด์ ๊ฐ๋ ๊ธฐ์ค๊ณผ ๋ง์ถ๊ธฐ ์ํ offset์ผ๋ก, ๋ก๋ดํ์ด ใท์ ๋ชจ์์ผ ๋, joint2๊ฐ 0๋์ด๊ธฐ๋ฅผ ๋ณด์ฅํ๋ offset ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ก๋ด joint2 ์์ฝ๋๊ฐ 0์ผ๋, ์ค์ ๋ก๋ดํ์ด 143๋๋ฅผ ์ด๋ฃจ๊ณ ์๋ค๋ฉด JOINT2_OFFSET = 143์ผ๋ก ์ค์ ํ์ฌ ๊ธฐ๊ตฌํ ๊ณ์ฐ์ ๋ณด์ ํฉ๋๋ค.
๋ก๋ดํ ๊ด์ ์ ๊ฐ๋ ํ๊ณ(์ ์ฝ)์ ๋ํ๋ ๋๋ค. ๋ก๋ดํ์ ๋ฌผ๋ฆฌ์ ์ ํ์ด๋ ์์ ๋ฒ์๋ฅผ ์ค์ ํ ๊ฐ์ผ๋ก, ๊ฐ ๊ด์ ์ด ์์ง์ผ ์ ์๋ ์ต์/์ต๋ ๊ฐ๋๋ฅผ ์๋ฏธํฉ๋๋ค.
์์ฝ๋ ์คํ ๋น ๊ฐ๋๋ฅผ ๋ํ๋ ๋๋ค. ์ฆ, ๊ด์ ์ ํ ์คํ ์์ง์์ ๋ ๋ช ๋๊ฐ ํ์ ๋๋์ง ์ ์ํฉ๋๋ค. ๊ธฐ๋ณธ ์ ์ ๊ฐ 0.0109...๋ 11.25 % 16 % 64๋ก ๊ณ์ฐ๋ ๊ฐ์ ๋๋ค.
ํ ๋ช ๋ น์ ํ์ฉ๋๋ ์ต๋ ์คํ ์ ์ ๋๋ค. ๋ชจ๋ motionJson์์์ ๋ช ๋ น์ MAX_STEPS_PT๋ฅผ ๋์ ์ ์์ต๋๋ค.
๋ ์ ์ฌ์ด ์ต๋ ํ์ฉ ๊ฐ๋ ๋ณํ๋ ์ ๋๋ค. #STEP_DEG * #MAX_STEPS_PT๋ฅผ ๊ณฑํ์ฌ ๊ณ์ฐ๋๋ฉฐ, ๊ธฐ๋ณธ์ ์ผ๋ก 0.07๋ ์ ๋๊ฐ ๋ฉ๋๋ค.
SVG ๊ฒฝ๋ก๋ฅผ ๋ก๋ด ์ขํ์ ๋งคํํ ๋์ ์ ๊ทํ ๋ฐ์ค ํฌ๊ธฐ ์ ๋๋ค. ๊ธฐ๋ณธ 250์ผ๋ก ๋งคํ๋์ด ์์ผ๋ฉฐ, ๋ก๋ดํ์ด (0,0) ~ (250,250) ๋ฐ์ค ์์ ์๋ ์ ๋ณด๋ ๊ทธ๋ฆด ์ ์์ด์ผ ํฉ๋๋ค. ์ฆ, ๋ก๋ด์ด ๊ทธ๋ฆด ๊ทธ๋ฆผ์ ์ต๋ ํฌ๊ธฐ๋ฅผ ์ ์ํ๋ค๊ณ ๋ณผ ์ ์์ต๋๋ค.
svg๊ฒฝ๋ก๋ก๋ถํฐ ์ถ์ถํ ์ ์ขํ ๋ฆฌ์คํธ ์ ๋๋ค. ์ด ๋ฆฌ์คํธ์๋ {x,y,pen}์ ํํ๋ก ๊ฐ์ฒด๋ค์ด ์์๋๋ก ๋ค์ด ์์ผ๋ฉฐ, ์ด ๊ฒฝ๋ก๋ฅผ ํตํด motionJson ์์ฑ์ ์งํํฉ๋๋ค.
๋ก๋ด ํ์ด ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ์์ง์ด๊ธฐ ์ํด ์ํํด์ผ ํ ์ธ๋ถ ๋ช ๋ น ๋ชฉ๋ก ์ ๋๋ค. ๊ฐ ๋ช ๋ น์{d1,d2,pen}์ ํํ๋ก ์ ์ฅ๋๋ฉฐ, d1, d2๋ ๋ค์ ๋ชฉ์ ์ง๋ก ๊ฐ๊ธฐ ์ํด ์์ง์ฌ์ผ ํ step ์ ์ ๊ฐ์ ๋ํ๋ ๋๋ค. ๋ํ pen์ ํด๋น ์ง์ ์์์ pen์ ์ํ(0 = ๋ค์ด์ฌ๋ฆผ, 1 = ๋ด๋ ค๋์)์ ๋๋ค. motionJson์ buildMotionJsonFromSvg()์์ ์์ฑ๋ฉ๋๋ค.
motionJson์ผ๋ก ์์ฑ๋ 1๋ฐ์ดํธ ๋ฐฐ์ด๋ก, d1,d2,pen์ ๊ฐ์ ๋ฐ๋ผ 1๋ฐ์ดํธ๋ก ์์ถํ์ฌ ํํํ ๋ฐฐ์ด์ ๋๋ค. plot์ ํํ ๋ฐฉ์์ ๋ํด์ [Plotto_Path]๋ฅผ ์ฐธ๊ณ ํด์ฃผ์ธ์
boolean ๊ฐ์ผ๋ก, ํ svg์ ๋ํด motionJson์ด ์์ฑ๋ ์ ์ด ์๋์ง์ ๋ํ ๋ณ์์ ๋๋ค. svg๊ฒฝ๋ก๋ฅผ ์ฒ๋ฆฌํ์ฌ motionJson๋ฅผ ๋ง๋ค๋ฉด, true๋ก ์ค์ ๋๋ฉฐ, configure()๋ฑ์ผ๋ก ์ค์ ์ด ๋ณ๊ฒฝ๋๋ฉด false๋ก ๋ฆฌ์ ๋ฉ๋๋ค. ์ด ๋ณ์๋ ๋์ผํ ๊ฒฝ๋ก์ ๋ํด motionJson ์ค๋ณต ์์ฑ์ ๋ฐฉ์งํ๋๋ฐ์ ์ฌ์ฉ๋ฉ๋๋ค.
new Plotto()๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด ํธ์ถ๋๋ ์์ฑ์์
๋๋ค.
$("encoder.joint_1").d = 0, $("encoder.joint_2").d = 0์ ๊ฐ์ ์์ฝ๋ ๊ฐ ์ด๊ธฐํ, $('pen').d = 0๋ก ์ด๊ธฐ๊ฐ์ ์ค์ ํฉ๋๋ค. ํ๋์ ์๋ ๋ณ์๋ค์ ํ๋ฒ์ ๋ณ๊ฒฝ ์์ configure() ํจ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
ํ๋์ ์๋ ๋ชจ๋ ๋ณ์๋ฅผ ํ๋ฒ์ ํจ์จ์ ์ผ๋ก ์ค์ ํ๋ ํจ์์ ๋๋ค. ๋งค๊ฐ๋ณ์๋ก ์ฌ๋ฌ ์ต์ ์ ๊ฐ์ฒด ํํ๋ก ๋ฐ์ผ๋ฉฐ, ๊ฐ ์ต์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
| ํญ๋ชฉ | ์ค๋ช | ๊ธฐ๋ณธ๊ฐ / ๋น๊ณ |
|---|---|---|
baseX, baseY
|
๋ก๋ด ํ ๋ฒ ์ด์ค(Joint 1)์ ๊ธฐ์ค ์ขํ๋ฅผ ์ค์ ํฉ๋๋ค. | (0, 0) |
link1Length |
์๋ถ ์(link1)์ ๊ธธ์ด๋ฅผ ์๋์ผ๋ก ์ง์ ํฉ๋๋ค. | ๋ฏธ์ง์ ์ initLinkGeometry()์์ ์ด๋ฏธ์ง ๊ธฐ๋ฐ ์๋ ๊ณ์ฐ |
link2Length |
์ ์(link2)์ ๊ธธ์ด๋ฅผ ์๋์ผ๋ก ์ง์ ํฉ๋๋ค. | ๋ฏธ์ง์ ์ initLinkGeometry()์์ ์ด๋ฏธ์ง ๊ธฐ๋ฐ ์๋ ๊ณ์ฐ |
upperRestAngle |
์๋ถ ์์ ๊ธฐ์ค ์์ธ ๊ฐ๋๋ฅผ ์ค์ ํฉ๋๋ค. (๋ผ๋์) | ๋ฏธ์ง์ ์ ์ด๋ฏธ์ง ๊ธฐ๋ฐ ์๋ ๊ณ์ฐ |
foreRestAngle |
์ ์์ ๊ธฐ์ค ์์ธ ๊ฐ๋๋ฅผ ์ค์ ํฉ๋๋ค. (๋ผ๋์) | ๋ฏธ์ง์ ์ ์ด๋ฏธ์ง ๊ธฐ๋ฐ ์๋ ๊ณ์ฐ |
JOINT2_OFFSET |
ํ๊ฟ์น(Joint 2) ๊ด์ ์ ๊ธฐ๊ณ์ ์คํ์ ๊ฐ๋๋ฅผ ์ค์ ํฉ๋๋ค. | 143ยฐ |
SVG_BOX_SIZE |
SVG ๊ฒฝ๋ก ์ ๊ทํ์ ์ฌ์ฉํ๋ ๊ธฐ์ค ๋ฐ์ค ํฌ๊ธฐ์ ๋๋ค. | 250 |
STEP_DEG |
์์ฝ๋ 1์คํ ๋น ํ์ ๊ฐ๋๋ฅผ ์ค์ ํฉ๋๋ค. | ๋ณ๊ฒฝ ์ MAX_DELTA_DEG ์๋ ์ฌ๊ณ์ฐ |
MAX_STEPS_PT |
ํฌ์ธํธ ๊ฐ ํ์ฉ๋๋ ์ต๋ ์์ฝ๋ ์คํ ์์ ๋๋ค. | ๋ณ๊ฒฝ ์ MAX_DELTA_DEG ์๋ ์ฌ๊ณ์ฐ |
minJoint1 |
Joint 1(์๋ถ ์)์ ์ต์ ๊ฐ๋ ์ ํ | ์ฌ์ฉ์ ์ค์ |
maxJoint1 |
Joint 1(์๋ถ ์)์ ์ต๋ ๊ฐ๋ ์ ํ | ์ฌ์ฉ์ ์ค์ |
minJoint2 |
Joint 2(์ ์)์ ์ต์ ๊ฐ๋ ์ ํ | ์ฌ์ฉ์ ์ค์ |
maxJoint2 |
Joint 2(์ ์)์ ์ต๋ ๊ฐ๋ ์ ํ | ์ฌ์ฉ์ ์ค์ |
๊ธฐ๊ตฌํ์ ํ๋ผ๋ฏธํฐ ์ค์ : ์ธ์์ ๋ฐ๋ผ #baseX, #baseY, #link1, #link2,upperRestAngle, foreRestAngle, JOINT2_OFFSET ๊ฐ์ ์ค์ ํฉ๋๋ค. ์ ๋ฌ๋์ง ์์ ๊ฐ์ ์ด์ ์ค์ ์ด๋ ๊ธฐ๋ณธ๊ฐ์ ์ ์งํฉ๋๋ค. SVG / ์์ํ ํ๋ผ๋ฏธํฐ ์ค์ : SVG_BOX_SIZE, STEP_DEG, MAX_STEPS_PT ๊ฐ์ ๊ฐฑ์ ํฉ๋๋ค. ์ด๋ STEP_DEG๋ MAX_STEPS_PT๊ฐ ๋ณ๊ฒฝ๋๋ฉด ๋ด๋ถ์ ์ผ๋ก #MAX_DELTA_DEG (์ต๋ ๊ฐ๋ ๋ณํ๋)๋ ์๋ก์ด ๊ฐ์ผ๋ก ์ ๋ฐ์ดํธ๋ฉ๋๋ค. ๊ด์ ์ ํ ์ค์ : ๋ง์ฝ ์๋ก์ด ๊ด์ ๊ฐ๋ ์ ํ ๊ฐ๋ค์ด ์ฃผ์ด์ง๋ฉด ํด๋น ๊ฐ์ ๋ฐ์ํฉ๋๋ค. ์ด์ ๊ฒฝ๋ก ๋ฐ์ดํฐ ์ด๊ธฐํ : ์ค์ ์ด ๋ณ๊ฒฝ๋์์ผ๋ฏ๋ก, #jsonBuilt๋ฅผ false๋ก ํ๊ณ , #motionJson๊ณผ #plot ๋ฐฐ์ด์ ๋น ๋ฐฐ์ด๋ก ์ด๊ธฐํํฉ๋๋ค. ๋ํ, initLinkGeometry()๋ฅผ ํธ์ถํ์ฌ, ํ์ฌ ์ด๋ฏธ์ง ์ ๋ณด ์ #link1, #link2, #upperRestAngle, #foreRestAngle์ ๊ณ์ฐํ์ฌ ํ๋์ ์ค์ ํฉ๋๋ค.
์ด ํจ์๋ ๊ด์ ๊ฐ๋(j1Deg, j2Deg)๋ฅผ ๋ฐ์ ํ ๋ ์ขํ(x3,y3)๋ฅผ ๊ณ์ฐํด ์ค๋๋ค.
๊ฐ๋ ๋ณํ : ์ฐ์ ๋ ๋จ์์ธ j1Deg๋ฅผ ๋ผ๋์์ ๋ง๊ฒ ๋ณํํ๋ฉฐ, ๋ถํธ๋ฅผ ๋ค์ง์ต๋๋ค(๋ก๋ด ์ขํ๊ฒ(์๊ณ -, ๋ฐ์๊ณ +)์ ๋ฐ๋์ด๊ธฐ ๋๋ฌธ). ์ด ๋ณํํ ์๋ฅผ theta1์ ์ ์ฅํฉ๋๋ค.
์ดํ theta1์ upperRestAngle์ ๋ํ ๊ฐ๋๋ฅผ theta1_ft์ ์ ์ฅํฉ๋๋ค. ์ด๋ ์ด๋ฏธ์ง ์์ ๋ก๋ดํ ๊ฐ๋๋ฅผ ๋ํ ์ค์ ๊ด์ ๊ฐ๋์ ๋๋ค.
j2Deg + this.JOINT2_OFFSET์ ๋ํ ์ค์ ๊ฐ๋ ๊ฐ์ ๋ผ๋์์ผ๋ก ๋ณํํ๊ณ ๋ถํธ๋ฅผ ๋ค์ง์ต๋๋ค. ์ด๋ฅผ theta2์ ์ ์ฅํฉ๋๋ค.
ํ๊ฟ์น ์ขํ(x2,y2) ๊ณ์ฐ :
๋ค์์ผ๋ก ์ขํ ๊ณ์ฐ์ ์งํํฉ๋๋ค. ์ ๊ธฐ๊ตฌํ ๊ณต์๊ณผ ๋์ผํฉ๋๋ค.
x2 = baseX + link1 * cos(theta1_fk);
y2 = baseY + link1 * sin(theta1_fk);(baseX, baseY)๋ ๋ก๋ด joint1 ๋ชจํฐ์ ์์น, link1์ ์๋ถ ์ ๊ธธ์ด์ ๋๋ค.
ํ ๋ ์ขํ(x3,y3) ๊ณ์ฐ :
x3 = x2 + link2 * cos(theta1_fk + theta2);
y3 = y2 + link2 * sin(theta1_fk + theta2);ํ๊ฟ์น์์๋ถํฐ theta2๋งํผ ๋ ํ์ ํ๋ฏ๋ก, ํ๊ฟ์น์์์ ์ ๋ ๊ฐ๋๋ theta1_ft + theta2๊ฐ ๋ฉ๋๋ค. ์ด ๋ฐฉํฅ์ผ๋ก link2๋งํผ ๋ ๋์๊ฐ ์ง์ ์ด ํ ๋ ์ขํ ์ ๋๋ค.
๊ฒฐ๊ณผ๋ก {x : x3, y : y3}๋ฅผ ๋ฐํํฉ๋๋ค.
์ด ํจ์๋ ๋ชฉํ ํ ์ขํ(targetX, targetY)๋ฅผ ์ฃผ๋ฉด, ํด๋น ์ง์ ์ ํ์ผ ์์น์ํค๊ธฐ ์ํ ๋ ๊ด์ ๊ฐ๋(joint1, joint2)๋ฅผ ๊ณ์ฐํฉ๋๋ค. 2DOF ํ๋ฉด ๋ก๋ด ํ ํ์ค ์ญ๊ธฐ๊ตฌํ ๊ณต์์ ๊ตฌํํ๊ณ ์์ผ๋ฉฐ, ๊ธฐ์กด ๊ฐ๋์ ๊ฐ๊น์ด ๊ฐ๋๋ฅผ ๋ฐํํฉ๋๋ค.
๋ชฉํ ์ ๊น์ง ๋ฒกํฐ ๊ณ์ฐ ๋ฐ ์์ ๊ณต๊ฐ ์ฒดํฌ : ๋ชฉํ์ ๊น์ง ์๋ ์ขํ๋ก ๊ฑฐ๋ฆฌ(d)๋ฅผ ๊ณ์ฐํ๊ณ , | L1 - L2 | (์ต์ ๊ฑฐ๋ฆฌ) ~ |L1 + L2| (์ต๋ ๊ฑฐ๋ฆฌ) ์์ ์๋์ง ๊ฒ์ฌํฉ๋๋ค.
์ญ ๊ธฐ๊ตฌํ ๊ฐ๋ ๊ณ์ฐ : ๋ชฉํ์ ์ด ๋๋ฌ ๊ฐ๋ฅ ํ๋ค๋ฉด, ์ผ๊ฐ๋ฒ์ ์ด์ฉํด ํ๊ฟ์น ๊ด์ ๊ฐ๋(theta2)๋ฅผ ๊ตฌํฉ๋๋ค.
let cos2 = (d * d - L1 * L1 - L2 * L2) / (2 * L1 * L2); // ์ผ๊ฐ๋ฒ์ผ๋ก theta2 ๊ตฌํ๊ธฐ
const theta2Abs = Math.acos(cos2);
const theta2List = [theta2Abs, -theta2Abs]; // theta2 ํ๋ณด(theta2๋ ์์ผ๋ก ๊ตฝํ ํ, ๋ฐ๊นฅ์ผ๋ก ๊ตฝํ ํ ๋๊ฐ์ง์.)๊ตฌํ ํ๊ฟ์น ๊ฐ๋๋ ์ ๋๊ฐ์ผ๋ก ๋๊ฐ์ง ๊ฒฝ์ฐ๊ฐ ์๋๋ฐ, ํ๊ฟ์น๊ฐ ์์ชฝ์ผ๋ก ๊ตฝํ ๊ฒฝ์ฐ์, ๋ฐ๊นฅ์ชฝ์ผ๋ก ๊ตฝํ ๊ฒฝ์ฐ์ ๋๋ค.
๊ฐ ํ๋ณด์ ๋ํด theta1 ๊ตฌํ๊ธฐ : ์ญ๊ธฐ๊ตฌํ์ ํตํด ์ด๊นจ๊ด์ ์ ๊ฐ๋ theta1๋ฅผ ์ป์ต๋๋ค.
k1 = L1 + L2 * cos(theta2_fk)
k2 = L2 * sin(theta2_fk)์ด ๊ฐ๋ค์ ์ญ๊ธฐ๊ตฌํ ๊ณต์์์ ์ค๊ฐ ๋จ๊ณ๋ก, ๋ ๋งํฌ์ ์ํด ํ์ฑ๋ ์ผ๊ฐํ์์ ์ด๊นจ ๊ด์ ๊ณผ ๋ชฉํ์ ์ฌ์ด ๊ฐ๋๋ฅผ ๊ตฌํ๋ ๋ฐ ์ฌ์ฉํ๋ ๋ณ์์ ๋๋ค.
const theta1_fk = Math.atan2(dy, dx) - Math.atan2(k2, k1);๋ฅผ ํตํด ๊ฐ๊ฐ theta2์ ๋ํ ์ ๋ ๊ฐ๋ theta1_fk๋ฅผ ๊ตฌํ๊ณ , offset ๋ฐ ์ด๋ฏธ์ง ๊ฐ๋๋ฅผ ์ ์ธํ ๊ธฐ์ค ์์ธ ๊ธฐ์ค(ใท ์์ธ ์ joint1 : 0, joint2 : 0๋) ๊ฐ๋ theta1, theta2๋ฅผ ๊ตฌํฉ๋๋ค.
ํด ๊ฒฐ์ : ์ดํ ๊ฐ๊ฐ theta1, theta2์ ๋ํด plotto์์ ์ ์ํ ์ต๋ ์ต์ ๊ฐ๋๋ฅผ ๋๋์ง ํ์ธํ๊ณ , ์ ํ ๊ฐ๋๋ฅผ ๋ฒ์ด๋๋ฉด ๊ทธ ํด๋ ์ฌ์ฉ ๋ถ๊ฐ๋ก ๊ฐ์ฃผํฉ๋๋ค.(aVaild ๋๋ bVaild = false)
์ดํ ๋ง์ฝ ๋ ๋ค ์ฌ์ฉ ๊ฐ๋ฅํ๋ค๋ฉด, ์ธ์๋ก ๋ฐ์ prevJ1Deg์ prevJ2Deg๋ฅผ ์ด์ฉํด ๋ ๊ฐ๊น์ด ๊ฐ๋๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
buildFromSvgText๋ svg ๊ฒฝ๋ก ๋ฌธ์์ด์ ๋ฐ์ ์ผ๋ จ์ ์ฒ๋ฆฌ๋ฅผ ๊ฑฐ์ฒ ๋ก๋ดํ์ ๊ฒฝ๋ก ๋ฐ์ดํฐ(#motionJson, #plot)๋ฅผ ๋ง๋ญ๋๋ค.
| ๋งค๊ฐ๋ณ์ | ํ์ | ์ค๋ช | ๊ธฐ๋ณธ๊ฐ / ๋น๊ณ |
|---|---|---|---|
svgText |
string |
SVG ํ์ผ์ ์ ์ฒด ํ ์คํธ ๋ด์ฉ์ ๋๋ค. ํ์ฑ๋์ด ๊ฒฝ๋ก(path) ๋ฐ์ดํฐ๋ก ๋ณํ๋ฉ๋๋ค. | ํ์ |
opts |
object |
SVG โ ๋ก๋ด ๊ฒฝ๋ก ๋ณํ ๊ณผ์ ์์ ์ฌ์ฉ๋๋ ์ต์ ๊ฐ์ฒด์ ๋๋ค. | ์ ํ |
| ์ต์ ๋ช | ํ์ | ์ค๋ช | ๊ธฐ๋ณธ๊ฐ / ๋น๊ณ |
|---|---|---|---|
k |
number |
์ ๊ทํ๋ SVG ๋ฐ์ค๋ฅผ ๋ก๋ด ์ขํ๊ณ๋ก ๋งคํํ ๋ ์ ์ฉ๋๋ ์ค์ผ์ผ ๊ณ์์ ๋๋ค. | 1.0 |
flipY |
boolean |
SVG ์ขํ๊ณ์ Y์ถ์ ์ํ ๋ฐ์ ํ ์ง ์ฌ๋ถ๋ฅผ ์ค์ ํฉ๋๋ค. | false |
maxDeltaDeg |
number |
ํฌ์ธํธ ๊ฐ ํ์ฉ๋๋ ์ต๋ ๊ด์ ๊ฐ๋ ๋ณํ๋(๋ ๋จ์)์ ๋๋ค. | this.MAX_DELTA_DEG |
svg ๊ฒฝ๋ก๋ฅผ ํตํด ์ด๊ธฐ ์ ๋ฐฐ์ด ์ถ์ถ : ๋งค๊ฐ๋ณ์ svgText๋ฅผ extractPathPointsFromSvg()๋ฅผ ํตํด ์ ๋ฐฐ์ด์ ์ถ์ถํ์ฌ, rawPts ๋ฐฐ์ด์ ์ ์ฅํฉ๋๋ค. ๋ฐํ๋ rawPts๋ {x,y,pen} ๊ฐ์ฒด๋ค์ ๋ฐฐ์ด๋ก, svg ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ์ํ๋ง ๋ ์ ์ ๋ด๊ณ ์์ต๋๋ค. ์ขํ ์ ๊ทํ : rawPts ๋ฐฐ์ด์ ์๋ณธ SVG ์ขํ๊ณ๋ฅผ ๋ฐ๋ฅด๋ ์ ๋ฐฐ์ด์ธ๋ฐ, ์ด๋ฅผ (0,0) ~ (SVG_BOX_SIZE,SVG_BOX_SIZE) ๋ฒ์์ ๋งคํํฉ๋๋ค. ์ด๋, SVG_BOX_SIZE x SVG_BOX_SIZE ํฌ๊ธฐ์ ๋ฐ์ค์ ์ต๋ํ ๊ฝ ์ฐจ๊ฒ ์ถ์/ํ๋ํ๊ณ ์์น๋ฅผ ๋ง์ถฅ๋๋ค. ์ด๋ ๊ฒ ์ ๊ทํํ ์ขํ๋ฅผ ptsBox์ ์ ์ฅํฉ๋๋ค. ๋ก๋ด ์ขํ๊ณ๋ก ๋งคํ : ptsBox๋ (0,0) ~ (SVG_BOX_SIZE,SVG_BOX_SIZE)๋ก ์ ๊ทํ ๋์ด ์๋๋ฐ,mapBoxToRobotTargets() ํจ์๋ฅผ ํตํด ์์์ 0,0์ด ์๋ baseX, baseY๋ถํฐ ์์ํ๋๋ก ํํ์ด๋ํฉ๋๋ค. ์ด ์ขํ๋ฅผ fitted ๋ฐฐ์ด์ ์ ์ฅํฉ๋๋ค. ๊ฐ๋ ๋ณํ ๊ธฐ๋ฐ ๋ฆฌ์ํ๋ง : ๋ก๋ดํ์ ์ขํ -> ์ขํ์ ์ด๋ ๊ฐ๋ ๋ณํ๊ฐ #MAX_DELTA_DEG๋ณด๋ค ๋ฎ๊ฒ ๋ฆฌ์ํ๋ง ํ๋ ์์ ์ ๋๋ค. ์ด ํจ์๋ฅผ ํตํด fitted ๋ฐฐ์ด์ ์๋ ์ขํ๊ฐ ๋ ๋ฏธ์ธํ๊ฒ ๋ถํ ๋๋ฉฐ, ๋ถํ ๋ ๋ฐฐ์ด์ด fitted์ ๋ค์ ์ ์ฅ๋ฉ๋๋ค. ์ํ ์ ์ฅ : fitted ๋ฐฐ์ด์ plotto.svgPathPoints์ ์ ์ฅํ๊ณ , this.jsonBuilt = false๋ก ์ค์ ํ์ฌ, ์์ง ์ด ์๋ก์ด ๊ฒฝ๋ก์ ๋ํ motionJson์ด ์์ฑ๋์ง ์์์์ ํ์ํฉ๋๋ค. motionJson ์์ฑ : ๋ง์ง๋ง์ผ๋ก buildMotionJsonFromSvg() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ, svgPathPoints๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ก๋ด ํ์ ์ธ๋ถ ๋์ ๋ช ๋ น ๋ชฉ๋ก์ ์์ฑํฉ๋๋ค. motionJson์ด ์์ฑ๋๋ฉด, ๋ด๋ถ์์ plotEncode()๋ฅผ ์ฌ์ฉํด ์ด ๋ช ๋ น๋ค์ ์ด์ง ํฌ๋งท์ผ๋ก ์์ถํ์ฌ this.plot ์์ฑ์ ์ ์ฅํฉ๋๋ค.
buildMotionJsonFromSvgํจ์๋ svgPathPoint๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์, ๋ก๋ด ํ ๊ฐ ๊ด์ ์ ๋ํ ์ธ๋ถ ์์ง์ ๋ช ๋ น ๋ฆฌ์คํธ motionJson์ ์์ฑํฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ก๋ดํ์ด ์ฒ์ ์์น์์ ์์ํ์ฌ ๊ฒฝ๋ก์ ๋ชจ๋ ์ ์ ๋ฐฉ๋ฌธํ๊ณ , ํ์ ์ฌ๋ฆฌ๊ฑฐ๋ ๋ด๋ฆฌ๋ ๋์๊น์ง ํฌํจํ ๋ช ๋ น์ด ๋ง๋ค์ด์ง๋๋ค. ์ด ๋, ๋ชจ๋ ๋ช ๋ น์ plotto์์ ์ ์๋ MAX_STEPS_PT๋ฅผ ๋์ง ์๋ ๋ช ๋ น์ผ๋ก ๋ณํํฉ๋๋ค.
์ด๊ธฐ ์ค์ ๋ฐ ์ ํจ์ฑ ์ฒดํฌ : ํจ์๊ฐ ํธ์ถ๋๋ฉด this.jsonBulit๋ฅผ ํ์ธํ์ฌ, plotto ๊ฐ์ฒด์์ motionJson์ด ๋ง๋ค์ด์ก๋์ง๋ฅผ ํ์ธํฉ๋๋ค. ๋ง๋ ์ ์ด ์๋ค๋ฉด ๋ค์ ๋ง๋ค์ง ์๊ณ ์ข ๋ฃํฉ๋๋ค. ๊ทธ๋ฐ๋ค์ plotto motionJson ๋ฆฌ์คํธ๋ฅผ ์ด๊ธฐํํ๊ณ , curStepJ1, curStepJ2(ํ์ฌ ๊ด์ ์์น๋ฅผ ์ถ์ ํ๋ ๋ณ์)๋ฅผ 0์ผ๋ก ์ด๊ธฐํํฉ๋๋ค. ๋ํ, ji ~ j2์ ๊ฐ๋ ์ต๋์ต์ ์คํญ์ ๋ํ๋ด๋ (j1MinStep ๋ฑ) ๋ณ์๋ ์คํญ ๋จ์๋ก ๊ฐ๋ ์ ํ์ ์ ์ฅํด๋ก๋๋ค.
์ด ๋ด๋ถ ํจ์๋ ํ์ฌ ๊ด์ ์์น์์ ๋ชฉํ ๊ด์ ์์น(targetJ1, targetJ2)๊น์ง ํ ์ํ penstate๋ก ์ด๋ํ๋๋ฐ ํ์ํ d1,d2 ๋ช
๋ น์ motionJson์ ์ถ๊ฐํฉ๋๋ค.
totalDiff1 = targetJ1 - curStepJ1, totalDiff2 = targetJ2 - curStepJ2, maxDiff = max(|totalDiff1|, |totalDiff2|) ์์ผ๋ก ๊ตฌํด์, ๋ง์ฝ maxDiff๊ฐ 0์ด๋ฉด ํ ์ํ๊ฐ ๋ฐ๋์ง ์์ผ๋ฉด motionJson์ ์ถ๊ฐํ์ง ์๊ณ , pen ์ํ๊ฐ ๋ฐ๋๋ ๊ฒฝ์ฐ๋ง motionJson์ ์ถ๊ฐํฉ๋๋ค.
maxDiff๊ฐ 0์ด ์๋๋ผ๋ฉด, ์ค์ ์์ง์์ด ํ์ํ ๊ฒ์ด๋ฏ๋ก, ํฐ ์์ง์์ ํ๋ฒ์ ํ์ง ์๊ณ MAX_STEPS_PT ์ดํ์ ์์ ๋จ๊ณ๋ก ์ชผ๊ฐ์ด ์ฌ๋ฌ ์์ง์์ผ๋ก ์ถ๊ฐํฉ๋๋ค.
rem1 = totalDiff1, rem2 = totalDiff2์ผ๋ก ๋จ์ ์ด๋ ์คํ
์ ์ ์ฅํ๊ณ , ๋ฐ๋ณต๋ฌธ์ ํตํด์ MAX_STEPS_PT๊น์ง ์๋ฆ
๋๋ค. ์ดํ $('pen').d = penState;๋ก ํ์ฌ ํ ์ํ๋ฅผ ์ง์ ํ๊ณ , ๋ฐ๋ณต๋ฌธ ์์์๋ ํ ์ํ๋ฅผ ๋ฐ๊พธ์ง ์์ผ๋ฉด์, rem1๊ณผ rem2๊ฐ 0์ด ๋ ๋๊น์ง ๋ฐ๋ณตํฉ๋๋ค. ์ด moveToTarget ํจ์๋ฅผ ํตํด ๋ชจ๋ d1, d2๊ฐ MAX_STEPS_PT ์ดํ๋ก ์ด๋ฃจ์ด์ง๋๋ค.
ํ ์์น -> ์ฒซ ๋ฒ์งธ ๊ฒฝ๋ก ์ ์ด๋ ๋ก๋ดํ์ด ์ฒ์์๋ ํ ์์น(Joint1 : 0๋, Joint2 : 0๋)์์ ์์ํ๋ค ๊ฐ์ ํ๊ณ , ๊ฐ์ฅ ์ฒ์์ผ๋ก ์งํํ๋ ์ผ์ svgPathPoints[0]์ ๊ฐ์ ธ์์, inverseKinematics2DOF()ํจ์๋ฅผ ํธ์ถํ๋ ์ผ ์ ๋๋ค. inverseKinematics2DOF()์, ์ฒ์ ์ ์์ ์์ํ๋ฏ๋ก, prevJ1=0, prevJ2=0์ผ๋ก ์ญ๊ธฐ๊ตฌํ ๊ณ์ฐ์ ์งํํฉ๋๋ค. ์ดํ ์ป์ ๊ฐ๋ ๊ฐ์ firstIk์ ๋ฐํํ์ฌ, firstIK๋ฅผ STEP ๋จ์๋ก ๋ณํ ํ, penState = 0(์์ํ ๋ ์ด๋ฏ๋ก)๋ก moveToTarget() ํจ์๋ฅผ ํธ์ถํฉ๋๋ค.
์ด ํธ์ถ๋ก ์ธํด ํ ์์น์์ ์ฒซ ์ ์ ์คํญ๊น์ง์ ๋ช ๋ น์ด plotto.motionJson์ ์ถ๊ฐ๋ฉ๋๋ค. ์ดํ ๊ณ์ฐํ ๊ฐ๋๋ฅผ prevJ1Deg, prevJ2Deg์ ์ ์ฅํฉ๋๋ค.
๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ์ ์ด๋ : ์ด์ svgPathPoint์ ๋ชจ๋ ์ ์ ์ฐจ๋ก๋๋ก ์ํํ๋ฉฐ ์ฒ๋ฆฌํฉ๋๋ค.
for (let idx = 0; idx < totalPoints; idx++) ๋ฐ๋ณต๋ฌธ์ ํตํด ์ํํฉ๋๋ค.
svgPathPoint์์ ์ขํ๋ฅผ ์ป์ด, inverseKinematics2DOF() -> moveToTarget() ๋ฅผ ๋ฐ๋ณตํฉ๋๋ค. ์ด๋, curStepJ1, curStepJ2, prevJ1Deg, prevJ2Deg๋ ์
๋ฐ์ดํธ ํฉ๋๋ค.
๋ง๋ฌด๋ฆฌ :
๋ฃจํ๊ฐ ๋๋ ํ, prevPen !==0(ํ์ด ๋ด๋ ค์ง ์ํ)๋ผ๋ฉด ํ์ ์ฌ๋ฆฌ๋ ๋ช
๋ น์ ์ถ๊ฐํฉ๋๋ค.this.motionJson.push({ d1: 0, d2: 0, pen: 0 })
์ดํ this.plot = plotEncode(this.motionJson);๋ฅผ ํตํด motionJson์ plot์ ์ ์ฅํฉ๋๋ค(1 byte ํํ)
๋ก๋ด ํ ์ด๋ฏธ์ง์ ์ ์๋ ๊ธฐ์ค ์ขํ๋ฅผ ์ด์ฉํด ์๋ถ ํ(link1)๊ณผ ํ๋ถ ํ(link2)์ ๊ธธ์ด์ ๊ธฐ์ค ์์ธ ๊ฐ๋(rest angle)๋ฅผ ๊ณ์ฐํ๋ ์ด๊ธฐํ ํจ์์ ๋๋ค. ์ด๋ ๊ฒ ๊ณ์ฐ๋ ๊ฐ๋ค์ ์ดํ ์ ยท์ญ๊ธฐ๊ตฌํ ๊ณ์ฐ ์ ์ด๋ฏธ์ง ๊ธฐ์ค๊ณผ ์ค์ ๊ด์ ๊ฐ๋ ๊ฐ์ ๋ณด์ ๊ฐ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
์๋ถ ํ ๊ธธ์ด ๊ตฌํ๊ธฐ : UPPER_JOINT_BASE์ UPPER_JOINT_ELBOW ์ขํ ๊ฐ์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํ์ฌ link1 ๊ธธ์ด๋ก ์ค์ ํฉ๋๋ค. ์ด ๋, scale์ ์ ์ฉํฉ๋๋ค. ์๋ถ ํ ์ด๋ฏธ์ง ๊ฐ๋ ๊ตฌํ๊ธฐ : ๋ ์ ์ ์ฐ๊ฒฐํ๋ ์ ์ ๋ฐฉํฅ์ atan2๋ก ๊ณ์ฐํ์ฌ upperRestAngle๋ก ์ ์ฅํฉ๋๋ค.
ํ๋ถ ํ ๊ธธ์ด ๊ตฌํ๊ธฐ : FORE_JOINT_ELBOW์ FORE_PEN ์ขํ ๊ฐ์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํ์ฌ link2 ๊ธธ์ด๋ก ์ค์ ํฉ๋๋ค.์ด ๋, scale์ ์ ์ฉํฉ๋๋ค. ํ๋ถ ํ ์ด๋ฏธ์ง ๊ฐ๋ ๊ตฌํ๊ธฐ : ๋ ์ ์ ์ฐ๊ฒฐํ๋ ์ ์ ๋ฐฉํฅ์ atan2๋ก ๊ณ์ฐํ์ฌ foreRestAngle๋ก ์ ์ฅํฉ๋๋ค.
์ฃผ์ด์ง ๊ฐ๋๋ฅผ โ180ยฐ ~ 180ยฐ ๋ฒ์๋ก ์ ๊ทํํ๋ ์ ํธ๋ฆฌํฐ ํจ์์ ๋๋ค.
์ ๋ ฅ๋ ๊ฐ๋๊ฐ 180ยฐ๋ฅผ ์ด๊ณผํ๋ฉด 360ยฐ๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ๋นผ์ ๋ฒ์ ์์ผ๋ก ๋ง์ถฅ๋๋ค. ์ ๋ ฅ๋ ๊ฐ๋๊ฐ -180ยฐ๋ณด๋ค ์์ผ๋ฉด 360ยฐ๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ๋ํด ๋ฒ์ ์์ผ๋ก ๋ง์ถฅ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ชจ๋ ๊ฐ๋๋ฅผ ๋์ผํ ๊ธฐ์ค ๋ฒ์๋ก ๋ณํํ์ฌ ๊ฐ๋ ๋น๊ต๋ ๋ณด๊ฐ ์ ๋ฐ์ํ ์ ์๋ ๋ถ์ฐ์ ๋ฌธ์ ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
extractPathPointsFromSvg(svgText, opts={}) ํจ์๋ SVG ์ด๋ฏธ์ง ์์ค (svgText)๋ฅผ ์ ๋ ฅ์ผ๋ก ๋ฐ์, ๊ทธ ์์ ํฌํจ๋ ๋ชจ๋ ๋ํ(graphic element)๋ค์ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ์ผ์ ๊ฐ๊ฒฉ์ ์ ๋ค์ ์ถ์ถํ๊ณ ์ด๋ฅผ ์ขํ ๋ฆฌ์คํธ๋ก ๋ฐํํ๋ ๊ธฐ๋ฅ์ ํฉ๋๋ค.
์ด ํจ์๋ ๋๊ฐ์ ์ธ์๋ฅผ ๋ฐ์ต๋๋ค. svgText : SVG ํ์ผ์ ์๋ณธ ํ ์คํธ ์ ๋๋ค. SVG๋ฅผ ๋ฌธ์์ด ํํ๋ก ์ ๊ณตํ๋ฉด, ํจ์๊ฐ ์ด๋ฅผ ํ์ฑํ์ฌ DOM ๊ตฌ์กฐ๋ก ๋ณํํฉ๋๋ค. opts : ๊ฒฝ๋ก ์ถ์ถ๊ณผ ์ํ๋ง ์ต์ ์ ๋ด์ ๊ฐ์ฒด์ ๋๋ค. ๊ธฐ๋ณธ๊ฐ์ {}์ด๋ฉฐ, ๋ค์๊ณผ ๊ฐ์ ์์ฑ์ ์ง์ ํ ์ ์์ต๋๋ค.
| ์ต์ ์ด๋ฆ | ํ์ / ๊ธฐ๋ณธ๊ฐ | ์ค๋ช |
|---|---|---|
| sampleStep | number / null
|
์ํ๋ง ๊ฐ๊ฒฉ๋ฅผ ์ง์ ์ง์ ํฉ๋๋ค. ์ด ๊ฐ์ด ์ฃผ์ด์ง๋ฉด ๊ฐ ๊ฒฝ๋ก๋ฅผ ๊ณ ์ ๋ ๊ฐ๊ฒฉ์ผ๋ก ์ํ๋งํ๋ฉฐ, samplesPerPath์ค์ ์ ๋ฌด์๋ฉ๋๋ค. |
| samplesPerPath | number / 200
|
๊ฐ ๋ํ์ ๊ฒฝ๋ก๋ฅผ ๋ช ๋ฑ๋ถ์ผ๋ก ๋๋์ง์ ๋ํ ๋๋ต์ ์ธ ๊ธฐ์ค์ ๋๋ค. ๊ฒฝ๋ก ์ ์ฒด๋ฅผ ์ด ๊ฐ์ผ๋ก ๋๋์ด ํ๊ท ๊ฐ๊ฒฉ์ ๊ณ์ฐํฉ๋๋ค. |
| maxStepClamp | number / 2
|
์ํ ๊ฐ๊ฒฉ์ ์ํ๊ฐ์ ์ง์ ํฉ๋๋ค. ๋๋ฌด ๊ธด ๊ฒฝ๋ก์ ๊ฒฝ์ฐ ๊ฐ๊ฒฉ์ด ์ง๋์น๊ฒ ์ปค์ง๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํ ๊ฐ์ผ๋ก, ๊ฐ๊ฒฉ์ด ์ด๋ณด๋ค ํฌ๋ค๋ฉด ์ด ๊ฐ์ผ๋ก ๊ณ ์ ๋ฉ๋๋ค. |
| maxSamplesPerPath | number / 3000
|
๊ฐ ๊ฒฝ๋ก๋น ์์ฑ๋ ์ ์๋ ์ต๋ ์ํ ์ ๊ฐฏ์์ ๋๋ค. |
| bridgeScale | number / 1.0
|
path๊ฐ ์ด๋ ๊ฒฝ๋ก์ ๋ฐ๋๋ฅผ ๊ฒฐ์ ํ๋ ์ค์ผ์ผ ๋ณ์์ ๋๋ค. |
opts๋ฅผ ํตํด ๊ฒฝ๋ก ์ํ๋ง ๊ฐ๊ฒฉ๊ณผ ๋ฐ๋๋ฅผ ์ธ๋ฐํ๊ฒ ์กฐ์ ํ ์ ์์ต๋๋ค.
DOM ๊ฐ์ฒด ์์ฑ : ํจ์๋ ์ฃผ์ด์ง SVG ํ ์คํธ๋ฅผ ํ์ฑํ์ฌ DOM ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค. ์ด ๋, DOM ํ์๋ฅผ์ด์ฉํ์ฌ ์ค์ SVG DOM ๊ฐ์ฒด๋ก(doc)๋ณํํฉ๋๋ค. ์์ SVG ์๋ฆฌ๋จผํธ ์์ฑ : ๋ณ์ ์ด๊ธฐํ : ์ต์ข ์ผ๋ก ๋ฐํํ ๋ฐฐ์ด์ธ points๋ฅผ ์ด๊ธฐํํฉ๋๋ค.(point์๋ {x, y, pen} ๊ฐ์ฒด๊ฐ ์์๋๋ก ์์ ๋๋ค.) ๋ํ, ์ด์ ๋ํ์ ๋ง์ง๋ง์ ์ ์ฅํ๋ lastGlobalPt๋ ์ด๊ธฐํํฉ๋๋ค.(์ฒซ ๋ํ ํ์ ๊ฐ์ ์ฑ์๋๋ค.), ์ด ๊ฐ์ path ๊ฐ ์ด๋ ๊ฒฝ๋ก๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
SVG ์์๋ค์ transfrom ์์ฑ์ ํตํด ํํ์ด๋, ํ์ , ์ค์ผ์ผ, ๊ธฐ์ธ์ด๊ธฐ(skew)๋ฑ์ ๋ณํ์ ๊ฐ์ง๋ฉฐ, <g> ๊ทธ๋ฃน์ ์ด์ฉํด์ ์์ ๊ทธ๋ฃน๋ค์ ๋ณํ์ด ๋์ ์ ์ฉ ๋ ์ ์์ต๋๋ค. spine ์ฝ๋์์ ์ด๋ฌํ ๋ณํ์ ์ ์ฉํ๊ธฐ ์ํด ๋ณํ affine ํ๋ ฌ์ ์ด์ฉํด์ ์ขํ๊ณ ๊ฒฝ๋ก๋ฅผ ๊ตฌํ๋ฉฐ, ์ด ํ๋ ฌ ์ ํธ๋ฆฌํฐ ํจ์์ ๋ํด ์๊ฐํ๊ณ ์ ํฉ๋๋ค.
ํญ๋ฑ ํ๋ ฌ์ ๋ฐํํฉ๋๋ค(a=1, d=1์ด๊ณ ๋๋จธ์ง 0์ธ ๋จ์ํ๋ ฌ)
์ด๋ ํ๋ ฌ์ ๋ฐํํฉ๋๋ค. x๋ฐฉํฅ tx, y ๋ฐฉํฅ ty๋งํผ ํํ์ด๋ ์ํค๋ ํ๋ ฌ์ ๋๋ค.
์ค์ผ์ผ ํ๋ ฌ์ ๋ฐํํฉ๋๋ค. x์ถ ๋ฐฉํฅ sx๋ฐฐ y์ถ ๋ฐฉํฅ sy๋ฐฐ ํ๋/์ถ์ ํฉ๋๋ค.
ํ์ ํ๋ ฌ์ ๋ฐํํฉ๋๋ค. ์ฃผ์ด์ง ๊ฐ๋ ๋งํผ ์์ ์ ์ค์ฌ์ผ๋ก ํ์ ํ๋ ํ๋ ฌ์ ๋๋ค.
X์ถ ๊ธฐ์ค ๊ธฐ์ธ์ด๊ธฐ ํ๋ ฌ์ ๋ฐํํฉ๋๋ค. ์ฃผ์ด์ง ๊ฐ๋ ๋งํผ x์ถ ๋ฐฉํฅ์ผ๋ก ๊ธฐ์ธ์ด๋ ๋ณํ์ ๋๋ค.
Y์ถ ๊ธฐ์ค ๊ธฐ์ธ์ด๊ธฐ ํ๋ ฌ์ ๋ฐํํฉ๋๋ค. ์ฃผ์ด์ง ๊ฐ๋ ๋งํผ y์ถ ๋ฐฉํฅ์ผ๋ก ๊ธฐ์ธ์ด๋ ๋ณํ์ ๋๋ค.
๋๊ฐ์ ํ๋ ฌ m1,m2๋ฅผ ๋ฐ์ ์์๋๋ก ํฉ์ฑํ ๊ฒฐ๊ณผ ํ๋ ฌ์ ๋ฐํํฉ๋๋ค.
"translate(...)", "rotate(...)"์ ๊ฐ์ SVG transform ์์ฑ ๋ฌธ์์ด์ ์ฝ์ด๋ค์ด๊ณ , ๊ทธ ๋ณํ๋ค์ ํฉ์ฑ ๊ฒฐ๊ณผ๋ฅผ ํ๋์ ํ๋ ฌ๋ก ๋ณํํ๋ ํจ์์ ๋๋ค. ์ ๊ท์์ผ๋ก "์ด๋ฆ" ํจํด์ ์ฐพ์์ ๊ฐ ๋ณํ๋ช ๋ น์ ์์๋๋ก ํด์ํ๋ฉฐ, ์์ ์ ์ํ ํ๋ ฌ ํจ์๋ค์ ์ด์ฉํฉ๋๋ค.
๊ฐ ๋ณํ ํ๋ ฌ m์ ์ด์ ๊น์ง์ ๋์ ํ๋ ฌ M์ ๊ณฑ์ ํ๋ฉฐ ํฉ์ฑํด ๋๊ฐ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด transform ๋ฌธ์์ด์ ๋์ด๋ ๋ณํ์ด ์์ฐจ ์ ์ฉ๋ ์ต์ข ํ๋ ฌ M์ ์ป๊ฒ ๋ฉ๋๋ค.
<g>๊ทธ๋ฃน์ ์ํ svg๋ ์์ ์ transform์ ํฌํจํ์ฌ ๋ถ๋ชจ๋ฅผ ๋ฐ๋ผ ์ต์์ svg๊น์ง ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๋ฉฐ ๋ชจ๋ ๋ณํ์ ํฉ์ฑํด์ผ ํฉ๋๋ค.
์ด ํจ์๋ ์์ ์์ฒด -> ๋ถ๋ชจ์ ๋ณํ .. ์์ผ๋ก ๋ชจ๋ ๊ณฑํ ์ ์ฒด ๋ณํ ํ๋ ฌ์ ๋ฐํํฉ๋๋ค.
<use> ์์๋ฅผ ๊ตฌํ ๋, ์๊ธฐ ์์ ์ transform์ ์ ์ฉํ๊ธฐ ์ ์์ ์์์ transform์ ์ ์ฉํด์ผ ํฉ๋๋ค.
์ด ํจ์๋ ์์ ์์ฒด์ ๋ณํ์ ์ ์ธํ๊ณ ๋ถ๋ชจ๋ค์ ๋์ ๋ณํ์ ๊ตฌํ์ฌ ๋ฐํํฉ๋๋ค.
์ค์ ๋ก ๊ทธ๋ ค์ง์ง ์๋ ์์๋ฅผ ์ ์ธํ๋ ํํฐ ํจ์์
๋๋ค.
์๋ฅผ ๋ค์ด, <defs>, display="none"์ ๊ฐ์ ์์๋ ๊ทธ๋ ค์ง์ง ์๋ ์์์ธ๋ฐ, ์ด์ ๊ฐ์ ๊ฒ์ ์ ์ธํฉ๋๋ค.
SVG ๋ด๋ถ์ ๊ฐ ๋ํ ์์๋ค์ ์์งํ๊ณ , ๊ฐ ์์ ๋ณ๋ก ๊ฒฝ๋ก ์ ๋ณด๋ฅผ ์ค๋นํฉ๋๋ค. ์ด ๋, ํฌ๊ฒ ๋๊ฐ์ง ์์๋ฅผ ๋ค๋ฃจ๋๋ฐ, ์ง์ ์ ์ธ ๊ทธ๋ํฝ ์์(path์ ๊ธฐ๋ณธ ๋ํ)์ <use>์ฐธ๊ณ ์์ ์
๋๋ค.
๊ธฐ๋ณธ ๊ทธ๋ํฝ ์์ ์ฒ๋ฆฌ
svgRoot.querySelectorAll("path, circle, rect, ellipse, line, polygon, polyline")๋ฅผ ์ด์ฉํ์ฌ svg ๋ด ๋ชจ๋ ๊ธฐ๋ณธ ๊ทธ๋ํฝ ์์๋ฅผ ์ ํํฉ๋๋ค.
์ด ๋, shouldRender(el)๋ฅผ ํตํด ๋ ๋๋ง ๋์์ธ์ง ํ์ธํ๊ณ , ๋ง๋ค๋ฉด allElements ๋ฐฐ์ด์ ์ถ๊ฐํฉ๋๋ค. ์ด ๋, ์ถ๊ฐ ์์ ์์์ ์ ๋ณด๋ ๊ฐ์ด ์ ์ฅํฉ๋๋ค.
allElements.push({
element: el, // ์์
transform: getAccumulatedTransformInclusive(el), // ๋์ ๋ณํ ํ๋ ฌ
tagName: el.tagName.toLowerCase() // ํ๊ทธ ๋ช
});<use> ์์ ์ฒ๋ฆฌ
svg์์๋ <use xlink:href="#id">์ ๊ฐ์ ํํ๋ก ์ฌ์ ์ ์ ์๋ ๋ํ์ ๋ณต์ฌํ์ฌ ์ธ ์ ์์ต๋๋ค.
<use> ์์๋ ์์ ์ ์์น(x, y ์์ฑ)์ ๋ณํ(transform ์์ฑ)์ ๊ฐ์ง ์ ์์ผ๋ฉฐ, ์ฐธ์กฐ ๋์ ์์์ ์ ์ ๋ณํ๊น์ง ํฉ์ณ์ ธ์ ์ต์ข
์์น๊ฐ ๊ฒฐ์ ๋ฉ๋๋ค.
์ฝ๋์์ svgRoot.querySelectorAll("use")๋ฅผ ํตํด ๋ชจ๋ <use>์์๋ฅผ ์ฐพ์ ๋ค, shouldRender(useEl)๋ก ํ์ธํ์ฌ ์ฒ๋ฆฌํฉ๋๋ค. ๊ฐ <use>์ ๋ํด resolveUseElement(useEl) ํจ์๋ฅผ ํธ์ถํ์ฌ ์ค์ ์ฐธ์กฐ๋ ์๋ณธ ์์์ ๊ทธ ๋ณํ ์ ๋ณด๋ฅผ ์ป์ต๋๋ค.
์ด ํจ์๋ <use> ์์์ ์๋ณธ ๋ํ + ์ฌ๋ฌ ๋จ๊ณ์ ๋ณํ์ ๋ชจ๋ ํด์ํด ํ๋์ ์ค์ ๋ํ์ผ๋ก ๋ณํํ ๋ค ๋ ๋๋ง ๋์์ ํฌํจ์ํค๋ ๊ณผ์ ์ ๊ฑฐ์น๋ค.
<use>์ href ์์ฑ์์ ์ฐธ์กฐ ๋์ ์ถ์ถ : <use> ์์์ href ๋๋ xlink:href ๊ฐ์ ์ฝ์ด #id ํํ์ ์ฐธ์กฐ ๋์ id๋ฅผ ์ถ์ถํ๊ณ , svgRoot.querySelector('#id')๋ก ์๋ณธ ๊ทธ๋ํฝ ์์๋ฅผ ์ฐพ์ต๋๋ค.
์๋ณธ ์์ ์กด์ฌ ํ์ธ : ๋ง์ฝ ์ฐธ์กฐ๋ id์ ํด๋น ์๋ณธ ์์๊ฐ ์กด์ฌํ์ง ์์ผ๋ฉด, ๊ฑด๋๋๋๋ค.
<use>์์์ x, y ์์ฑ์ ํํ์ด๋ ํ๋ ฌ๋ก ๋ณํ : <use> ์์์ x,y ์์ฑ์ ์ฝ์ด (x,y)๋ก ์ด๋์ํค๋ ํํ์ด๋ ํ๋ ฌ T๋ก ๋ณํํฉ๋๋ค.
๋ณํ ํ๋ ฌ ์์ง : <use>๋ก ์ธํด ์ ์ฉ๋๋ ๋ชจ๋ ๋ณํ์ ๋ค์ ๋ค๊ฐ์ง ์ข
๋ฅ๋ก ๋ถ๋ฆฌํ์ฌ ์์งํฉ๋๋ค.
| ๊ตฌ๋ถ | ์ค๋ช |
|---|---|
| ๋ถ๋ชจ ๊ทธ๋ฃน ๋ณํ |
<use> ์์์ ์์ <g> ์์๋ค์ ์ ์ฉ๋ transform์ ๋์ ํ ๋ณํ ํ๋ ฌ |
<use> ์์ฒด ๋ณํ |
<use> ์์์ ์ง์ ์ง์ ๋ transform ์์ฑ์ผ๋ก๋ถํฐ ์์ฑ๋ ๋ณํ ํ๋ ฌ |
<use> ์์น ์ด๋ |
<use> ์์์ x, y ์์ฑ์ผ๋ก๋ถํฐ ์์ฑ๋ ํํ์ด๋(translate) ํ๋ ฌ |
| ์๋ณธ ์์ ๋ณํ |
<use>๊ฐ ์ฐธ์กฐํ๋ ์๋ณธ ๊ทธ๋ํฝ ์์(ref)์ ์ ์ฉ๋ transform ์์ฑ์ผ๋ก๋ถํฐ ์์ฑ๋ ๋ณํ ํ๋ ฌ |
์ต์ข
๋ณํ ํ๋ ฌ ํฉ์ฑ : ์์ง๋ ๋ณํ ํ๋ ฌ์ ๋ถ๋ชจ -> <use> -> x,y ์ด๋ -> ์๋ณธ ์์ ๋ณํ ์์ผ๋ก ์ ์ฉํ์ฌ ํ๋์ ํ๋ ฌ๋ก ํฉ์ฑํฉ๋๋ค.
<use> ํด์ ๊ฒฐ๊ณผ ๊ฐ์ฒด ์์ฑ : ํด์๋ <use> ์์์ ๋ํด ๋ค์ ์ ๋ณด๋ฅผ ํฌํจํ๋ ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค.
๋ ๋๋ง ๋์์ ์ถ๊ฐ : ์์์ ํด์๋ ๊ฐ์ฒด๋ฅผ allElements ๋ฐฐ์ด์ ์ถ๊ฐํ์ฌ, ๋ ๋๋ง ์ฒ๋ฆฌ์ ํฌํจํฉ๋๋ค.
์ด ๋จ๊ณ๊น์ง ์๋ค๋ฉด, allElements ๋ฐฐ์ด์๋ SVG ๋ด ๋ชจ๋ ์ฒ๋ฆฌ ๋์ ๋ํ์ด ๋ฑ๋ก๋์ด ์์ต๋๋ค.
SVG๋ด์๋ path ์์ ์ธ์๋ <circle>,<rect> ๋ฑ ๋ค์ํ ๊ธฐ๋ณธ ๋ํ์ด ์์ต๋๋ค. ์ด ํจ์์์๋ ๋ชจ๋ ๋ํ์ path ๋ฐ์ดํฐ๋ก ๋ณํํ์ฌ ์ฒ๋ฆฌํฉ๋๋ค.
์์ path๋ก ๋ณํํ๊ธฐ ์ํด ๋๊ฐ์ ํธ๋ก ํํํฉ๋๋ค. svg path์ A(์ํธ) ๋ช
๋ น์ ์ด์ฉํ์ฌ ๋๊ฐ์ ํธ๋ก ์์ ๊ตฌ์ฑํฉ๋๋ค.
<circle>์์์ cx, cy, r ์์ฑ์ ์ฝ์ด ์ค์ฌ ์ขํ์ ๋ฐ์ง๋ฆ์ ์ป์ต๋๋ค.
์์ ๊ฐ์ฅ ์ผ์ชฝ ์ (cx-r, cy)์์ M ๋ช
๋ น์ผ๋ก ๊ฒฝ๋ก๋ฅผ ์์ํฉ๋๋ค.
์ฒซ ๋ฒ์งธ A r r 0 1 1 ๋ช
๋ น์ผ๋ก ์ค๋ฅธ์ชฝ ์ (cx + r, cy)๊น์ง ๋ฐ์์ ๊ทธ๋ฆฝ๋๋ค. ์ดํ ๋ ๋ฒ์งธ A r r 0 1 1 ๋ช
๋ น์ผ๋ก ๋ค์ ์์์ (cx - r, cy)๊น์ง ๋ฐ์์ ๊ทธ๋ฆฝ๋๋ค. ๋ง์ง๋ง์ Z ๋ช
๋ น์ผ๋ก ๊ฒฝ๋ก๋ฅผ ๋ซ์ ํ๋์ ์์ ํ ์ path๋ฅผ ์์ฑํฉ๋๋ค.
์ด ๋ฐฉ์์ผ๋ก ๋๊ฐ์ ํธ๊ฐ ์ฐ๊ฒฐ๋์ด ํ๋์ ์ ๊ฒฝ๋ก๊ฐ ๋ฉ๋๋ค.
ํ์์ circle๊ณผ ๊ฑฐ์ ๋์ผํ ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌ ๋๋ฉฐ, XยทY ๋ฐฉํฅ ๋ฐ์ง๋ฆ์ด ์๋ก ๋ค๋ฅธ ์์ผ๋ก ์๊ฐํ ์ ์์ต๋๋ค.
<ellipse> ์์์ cx, cy, rx, ry ์์ฑ์ ์ฝ์ต๋๋ค. ์ดํ (cx - rx, cy)์์ M ๋ช
๋ น์ผ๋ก ์์ํ๋ฉฐ, A rx ry 0 1 1 ๋ช
๋ น์ผ๋ก (cx + rx, cy)๊น์ง ๋ฐ์์ ๊ทธ๋ฆฝ๋๋ค.
๋ค์ A rx ry 0 1 1 ๋ช
๋ น์ผ๋ก ์์์ ๊น์ง ์ด์ด์ค๋๋ค. ๋ง์ง๋ง์ผ๋ก Z ๋ช
๋ น์ผ๋ก ๊ฒฝ๋ก๋ฅผ ๋ซ์ ํ๋์ ํ์ path๋ฅผ ์์ฑํฉ๋๋ค.
์ฌ๊ฐํ์ rx, ry(๋ชจ์๋ฆฌ ๋ฐ๊ฒฝ)์ ๋ฐ๋ผ ๋๊ฐ์ง ๋ฐฉ์์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค.
๊ณตํต ์ฒ๋ฆฌ x, y, width, height, rx, ry ์์ฑ์ ์ฝ์ต๋๋ค. ์ฌ๊ธฐ์ rx, ry๊ฐ ์์ผ๋ฉด 0์ผ๋ก ์ฒ๋ฆฌํ๊ณ , ํ๋๋ง ์ง์ ๋ ๊ฒฝ์ฐ ๋ ๊ฐ์ ๋์ผํ๊ฒ ๋ง์ถฅ๋๋ค. ๋ํ, rx > width / 2 ์ด๋ฉด width / 2๋ก ์ ํํ๊ณ , ry > height / 2 ์ด๋ฉด height / 2๋ก ์ ํํฉ๋๋ค.
๋ชจ์๋ฆฌ๊ฐ ๋ฅ๊ทผ ์ฌ๊ฐํ(rx > 0 && ry > 0) rx > 0 ์ด๊ณ ry > 0 ์ธ ๊ฒฝ์ฐ, ๊ฐ ๋ชจ์๋ฆฌ๋ฅผ ํ์ 1/4 ํธ์ ๊ทผ์ฌํ ๋ฒ ์ง์ด ๊ณก์ ์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค. ์์ 1/4์ ํ๋น ๋ฒ ์ง์ด๋ก ๊ทผ์ฌํ๊ธฐ ์ํด K = 0.5522847498307936 ์์๋ฅผ ์ฌ์ฉํ๋ฉฐ, ๊ฐ ๋ชจ์๋ฆฌ์ ๋ํด ox = rx * K, oy = ry * K ๊ฐ์ ๊ณ์ฐํฉ๋๋ค. ์ง์ (L)๊ณผ ํ๋น ๋ฒ ์ง์ด(C) ๋ช ๋ น์ ์กฐํฉํ์ฌ ๋ค ๋ชจ์๋ฆฌ๋ฅผ ๋ถ๋๋ฝ๊ฒ ์ฐ๊ฒฐํฉ๋๋ค. ์ดํ ๋ค ๋ชจ์๋ฆฌ๋ฅผ ๋ชจ๋ ์ฐ๊ฒฐํ ํ Z ๋ช ๋ น์ผ๋ก ๊ฒฝ๋ก๋ฅผ ๋ซ์ต๋๋ค.
์ด ๊ฒฐ๊ณผ, ์๋ rect์ ๋ฅ๊ทผ ๋ชจ์๋ฆฌ๋ฅผ rx, ry ๋ฐ์ง๋ฆ์ ํ์ ํธ์ ๊ทผ์ ํ path๋ก ๋ณํํฉ๋๋ค.
๋ชจ์๋ฆฌ๊ฐ ์ง๊ฐ์ธ ์ฌ๊ฐํ(rx <=1e-9 && ry <=1e-9) M x,y๋ก ์์ํ ๋ค, ์๊ณ ๋ฐฉํฅ์ผ๋ก ๋ค ๊ฐ์ L ๋ช ๋ น์ ์ฌ์ฉํด ๊ผญ์ง์ ์ ์ฐ๊ฒฐํฉ๋๋ค. ๋ง์ง๋ง์ Z ๋ช ๋ น์ผ๋ก ๊ฒฝ๋ก๋ฅผ ๋ซ์ ๋จ์ ์ฌ๊ฐํ path๋ฅผ ์์ฑํฉ๋๋ค.
<line> ์์๋ ์์์ (x1, y1)๊ณผ ๋์ (x2, y2)์ ๊ฐ์ง๋ ๋จ์ ์ ๋ถ์
๋๋ค.
M x1,y1 โ L x2,y2 ํํ์ path๋ก ๋ณํํฉ๋๋ค.
<polygon> ์์์ points ์์ฑ์ ํ์ฑํ์ฌ ์ขํ ๋ฐฐ์ด์ ์ป์ต๋๋ค.
์ฒซ๋ฒ์งธ ์ ์ M ๋ช
๋ น์ผ๋ก ์ค์ ํ๋ฉฐ, ์ดํ ๊ฐ ์ ๋ง๋ค L ๋ช
๋ น์ ์ถ๊ฐํ์ฌ ์ง์ ์ ๊ทธ๋ฆฝ๋๋ค.
polygon์ ๋ซํ ๋ํ์ด๋ฏ๋ก ๋ง์ง๋ง์ Z ๋ช
๋ น์ ์ถ๊ฐํ์ฌ ๊ฒฝ๋ก๋ฅผ ๋ซ์ต๋๋ค.
<polygon> ์์์ points ์์ฑ์ ํ์ฑํ์ฌ ์ขํ ๋ฐฐ์ด์ ์ป์ต๋๋ค.
์ฒซ๋ฒ์งธ ์ ์ M ๋ช
๋ น์ผ๋ก ์ค์ ํ๋ฉฐ, ์ดํ ๊ฐ ์ ๋ง๋ค L ๋ช
๋ น์ ์ถ๊ฐํ์ฌ ์ง์ ์ ๊ทธ๋ฆฝ๋๋ค.
polygon์ ์ด๋ฆฐ ๊บพ์ ์ ์ด๋ฏ๋ก ๋ง์ง๋ง์ Z ๋ช
๋ น์ ์ถ๊ฐํ์ฌ ๊ฒฝ๋ก๋ฅผ ๋ซ์ต๋๋ค.
์ด์ ๋ชจ๋ ์์์ ๋ํด path ๋ฐ์ดํฐ๊ฐ ์ค๋น๋์์ผ๋ฏ๋ก, ๊ฐ ๊ฒฝ๋ก์ ๊ธธ์ด๋ฅผ ๊ณ์ฐํ๋ ๋จ๊ณ๋ฅผ ๊ฑฐ์นฉ๋๋ค. ๊ฐ ๊ฒฝ๋ก์ ๊ธธ์ด๋ฅผ ๊ตฌํ๋ ์ด์ ๋, ์ ์ํ๋ง ๊ฐ๊ฒฉ์ ๊ฒฐ์ ํ๊ณ ์ต์ ํ ํ๊ธฐ ์ํด์์ ๋๋ค. ์ฝ๋์์๋ ๋ชจ๋ ์์์ ๋ํด ๋ค์ ๊ณผ์ ์ ์ํํ๊ณ , ๊ฒฐ๊ณผ๋ฅผ prepared๋ผ๋ ์๋ก์ด ๋ฐฐ์ด์ ๋ชจ์๋๋ค.
์์ path ์์ ์์ฑ : ๊ฐ ์์์ ๋ํด ์์ ์ป์ด๋ path ๋ฐ์ดํฐ ๋ฌธ์์ด๊ณผ, ๋์ ๋ณํ ํ๋ ฌ์ ๊บผ๋
๋๋ค. ์ดํ document.createElementNS(..., "path")๋ก ์๋ก์ด <path> ์์๋ฅผ ์์ฑํ๊ณ , ํด๋น ๊ฒฝ๋ก ๋ฌธ์์ด์ d ์์ฑ์ ์ง์ ํฉ๋๋ค.
๋ง์ฝ ๋์ ๋ณํ ํ๋ ฌ์ด ์กด์ฌํ๋ค๋ฉด, ์ด path ์์์ ํ๋ ฌ์ ์ ์ฉํฉ๋๋ค. ํ๋ ฌ m์ด {a, b, c, d, e, f}๋ผ๋ฉด pathEl.setAttribute("transform", "matrix(a,b,c,d,e,f)") ํํ๋ก ์ง์ ํฉ๋๋ค. ์ด๋ฅผ ํตํด path๊ฐ ์ค์ ํ๋ฉด ์ขํ๊ณ์์ ๋ณํ๋ ๋ชจ์์ผ๋ก ์ทจํด์ง๋๋ค.
์ด path ์์๋ฅผ ์๊น ๋ง๋ tempSvg (์จ๊ฒจ์ง SVG) ๋ด๋ถ์ ์ถ๊ฐํฉ๋๋ค. ์ด๋ฌ๋ฉด ๋ธ๋ผ์ฐ์ ์์ง์ด ํด๋น path์ ๊ธธ์ด์ ๋ชจ์์ ๊ณ์ฐํ ์ ์๋ ์ํ๊ฐ ๋ฉ๋๋ค.
๊ฒฝ๋ก ๊ธธ์ด ์ธก์ : pathEl.getTotalLength()๋ฅผ ํธ์ถํ์ฌ ํด๋น path (๋ณํ ์ ์ฉ๋)์ ์ ์ฒด ๊ธธ์ด (L)๋ฅผ ์ป์ต๋๋ค.
๊ธธ์ด๊ฐ ์ ํจํ๊ฒ ๊ณ์ฐ๋ ๊ฒฝ์ฐ (L > 0), ํ์ฌ ์์์ ์ ๋ณด๋ฅผ prepared ๋ฐฐ์ด์ ์ถ๊ฐํฉ๋๋ค.
prepared.push({ dAttr, transformMatrix, length: L });
์ด์ prepared์ ๊ฒฝ๋ก ๋ฐ์ดํฐ์ ๊ธธ์ด๊ฐ ๋ชจ์ด๊ฒ ๋๊ณ , ์ด ์ ๋ณด์ ๊ธฐ๋ฐํ์ฌ ์ ์ํ๋ง์ ์ํํฉ๋๋ค.
prepared์ ๋ด๊ธด ๊ฐ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ์ผ์ ํ ๊ฐ๊ฒฉ์ผ๋ก ์ ์ ์ฐ์ด points ๋ฐฐ์ด์ ๋์ ํฉ๋๋ค. ์ํ๋ง ๋จ์๋ opts์ ๊ฒฝ๋ก์ ๊ธธ์ด์ ์ํด ๊ฒฐ์ ๋๊ณ , ๊ฐ ๋ํ์ bridge ๋ถ๋ถ๋ ํจ๊ป ์ฒ๋ฆฌ๋ฉ๋๋ค.
์ํ๋ง ๋ฃจํ ์์ :
์ํ๋ง ๊ฐ๊ฒฉ ์ค์ : ์ต์ ์ผ๋ก sampleStep์ด ์ฃผ์ด์ก๋ค๋ฉด, step = sampleStep์ผ๋ก ์ค์ ํฉ๋๋ค. sampleStep์ด ์๋ค๋ฉด, ์ด ๊ฒฝ๋ก์ ๊ธธ์ด๋ฅผ samplePerPath๋ก ๋๋ ๊ฐ์ผ๋ก step์ ์ ํฉ๋๋ค. ์ด ๋, ์ด๋ ๊ฒ ๊ณ์ฐํ step์ด maxStepClamp๋ณด๋ค ํฐ ๊ฒฝ์ฐ, step = maxStepClamp๋ก ์ํ์ ์ ํํฉ๋๋ค.(๋๋ฌด ๊ฐ๊ฒฉ์ด ์ปค์ง๋ ๊ฒ์ ๋ฐฉ์ง)
์ต๋ ์ ์ ์ ํ : ๊ฒฝ๋ก๊ฐ ๋งค์ฐ ๊ธธ์ด์ step ๊ฐ๊ฒฉ์ผ๋ก ์ฐ์ผ๋ฉด ์ ๊ฐ์๊ฐ maxSamplePerPath๋ฅผ ์ด๊ณผํ ๊ฒฝ์ฐ, ๊ฐ๊ฒฉ์ ์กฐ๊ธ ๋๋ ค ์ ๊ฐ์๋ฅผ ์ ํํฉ๋๋ค. ์ด ๊ณผ์ ์ผ๋ก ์ต์ข step์ด ๊ฒฐ์ ๋ฉ๋๋ค.
๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ์ ์ฐ๊ธฐ : ์ด์ ๋ฃจํ๋ฅผ ๋๋ฉฐ, ๊ฒฝ๋ก๋ฅผ ์์๋ถํฐ ๋๊น์ง step ๊ฐ๊ฒฉ์ผ๋ก ๋ฐ๋ผ๊ฐ๋ฉด์ ์ขํ๋ฅผ ์ํ๋งํฉ๋๋ค.
len์ step์ ๋ํด๊ฐ๋ฉด์ ๋ฃจํ๊ฐ ์งํ๋๋ฉฐ, pathEl.getPointAtLength(len)๋ฅผ ํตํด len ๊ฑฐ๋ฆฌ๋งํผ ๋จ์ด์ง ์ง์ ์ ์ขํ๋ฅผ ๊ฐ์ฒด๋ก ๋ฐํํ๊ณ , isFirst๊ฐ true์ผ์, pen์ 0, ์๋ ์ pen์ 1๋ก ์ฒ๋ฆฌํ์ฌ localPoints์ ์ ์ฅํฉ๋๋ค.์ดํ isFirst๋ฅผ false๋ก ๋ณ๊ฒฝํฉ๋๋ค(์ด๋ก์จ, path ์ฒซ ์ ์ดํ๋ ๋ชจ๋ pen 1๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค.)
๋ํ, ๋ฃจํ ์ข ๋ฃ ํ, ๋ณ๋๋ก pathEl.getPointAtLength(totalLength)๋ฅผ ํธ์ถํ์ฌ ๊ฒฝ๋ก์ ๋ง์ง๋ง ์ ์ ์ป๊ณ , ์ด๋ฅผ localPoints์ ์ถ๊ฐํฉ๋๋ค.
์์ path ์ ๊ฑฐ : ์ฌ์ฉ์ด ๋๋ pathEl์ ๋ค์ tempSvg.removeChild(pathEl)๋ก ์ ๊ฑฐํฉ๋๋ค. ์ด๋ ๊ฒฝ๋ก ๊ฒน์นจ ๋ฌธ์ ๋ฅผ ํผํ๊ณ , ๋ฉ๋ชจ๋ฆฌ ์๋น๋ฅผ ์ค์ด๊ธฐ ์ํด์ ์ ๋๋ค.
๋ํ ๊ฐ bridge ์ถ๊ฐ : ํ ๋ํ์ ์ ์ points์ ์ถ๊ฐํ๊ธฐ ์ ์, ๋ง์ฝ ์ด์ ๋ํ์ ๋ง์ง๋ง ์์น๊ฐ ์์ ๊ฒฝ์ฐ(lastGlobalPt๊ฐ null์ด ์๋ ๊ฒฝ์ฐ), ๊ทธ ์ ์์ ํ์ฌ ์ ๊ฒฝ๋ก์ ์ฒซ ์ ๊น์ง ํ์ ๋ค์ด ์ด๋ํ๋ ๊ฒฝ๋ก๋ฅผ ์ถ๊ฐ๋ก ์ํ๋งํฉ๋๋ค. bridge ์ํ๋ง ๋ฐ๋๋ ๊ธฐ๋ณธ step์ opts.bridgeScale๋ฅผ ๊ณฑํด ์กฐ์ ํฉ๋๋ค. ์์ : bridgeStep = step * bridgeScale bridge ๊ตฌ๊ฐ์ ํ์ ๋ ์ด๋์ด๋ฏ๋ก, pen์ 0์ผ๋ก ๊ธฐ๋กํฉ๋๋ค.
์ ๋์ ๋ฐ lastGlobalPt ๊ฐฑ์ : 29. ์ด์ ๋ธ๋ฆฌ์ง ์ (๋ง์ฝ ์๋ค๋ฉด)์ด points์ ์ถ๊ฐ๋ ์ํ์์, ํ์ฌ ๋ํ์ ์ค์ ๊ฒฝ๋ก ์ ๋ค(localPoints ๋ฐฐ์ด)์ ์์๋๋ก points ๋ฐฐ์ด์ ์ด์ด๋ถ์ ๋๋ค. ์ดํ lastGlobalPt๋ฅผ localPoints์ ๋ง์ง๋ง ์ ์ผ๋ก ์ ๋ฐ์ดํธ ํฉ๋๋ค. ๋ชจ๋ prepared ํญ๋ชฉ์ ๋ํด ์ ๊ณผ์ ์ ๋ง์น๋ฉด, points ๋ฐฐ์ด์๋ SVG์ ๋ชจ๋ ๋ํ ๊ฒฝ๋ก๋ฅผ ๋ฐ๋ผ ์์ฑ๋ ์ ์ด ์์๋๋ก ๋ด๊ธฐ๊ฒ ๋ฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก tempSvg (์์๋ก ๋ง๋ค์๋ ๋ณด์กฐ SVG ์์)๋ฅผ document.body.removeChild(tempSvg)๋ก ์ ๊ฑฐํ์ฌ, ํ๋ฉด์ ๋ณด์ด์ง ์๊ฒ ์์ฑํ๋ ์์๋ฅผ ์ ๋ฆฌํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ points ๋ฐฐ์ด์ returnํ์ฌ ํจ์ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋ณด๋ ๋๋ค.
์ด ํจ์์ ๋ฐํ๊ฐ points๋ ๋ค์๊ณผ ๊ฐ์ javascript ๋ฐฐ์ด์ ๋๋ค.
[
{ x: Number, y: Number, pen: Number },
{ x: Number, y: Number, pen: Number },
...
]์ด ๊ฒฐ๊ณผ๋ฅผ ํตํด, ์ขํ -> ๋ก๋ด์ step ์ฆ๋ถ๊ฐ ์ผ๋ก ๋ฐ๊พธ๋ ์ฒ๋ฆฌ๋ฅผ ๊ฑฐ์ฒ, ๋ก๋ด์ด ์ด์ฉ ๊ฐ๋ฅํ ๋ช ๋ น์ผ๋ก ๋ณ๊ฒฝํ๊ฒ ๋ฉ๋๋ค.
normalizeToBox ํจ์๋ points์ ๋ชจ๋ ์ ์ 0 ~ SVG_BOX_SIZE ๋ฒ์์ ๋งคํํฉ๋๋ค. ์ฆ ๊ทธ๋ฆผ์ SVG_BOX_SIZE x SVG_BOX_SIZE ํฌ๊ธฐ์ ๋ฐ์ค์ ์ต๋ํ ๊ฝ ์ฐจ๊ฒ ์ถ์/ํ๋ํ๊ณ ์์น๋ฅผ ๋ง์ถฅ๋๋ค.
์ต๋ ์ต์ ๊ฐ ์ฐพ๊ธฐ : points์ ์ ์ ๋ชจ๋ ์ํํ๋ฉฐ minX, maxX, minY, maxY๋ฅผ ๊ตฌํฉ๋๋ค.
์๋ณธ ๊ฒฝ๋ก์ ํญ๊ณผ ๋์ด ๊ณ์ฐ : w = maxX - minX , h = maxY - minY์ ๊ฐ์ ์์ผ๋ก ์๋ณธ points์ ํญ๊ณผ ๋์ด๋ฅผ ๊ณ์ฐํฉ๋๋ค.
์ ๊ทํ ์ค์ผ์ผ ๊ณ์ฐ : ๊ฒฝ๋ก๊ฐ SVG_BOX_SIZE์ ๋ค์ด์ค๋๋ก ๋ ํฐ ๊ธธ์ด๋ฅผ ๊ธฐ์ค์ผ๋ก ์ค์ผ์ผ ๊ณ์ s๋ฅผ ๊ณ์ฐํฉ๋๋ค.
s = SVG_BOX_SIZE / max(w, h)
์ค์ ์ ๋ ฌ์ ์ํ ์คํ์
๊ณ์ฐ : ์ค์ผ์ผ ์ ์ฉ ํ, ๋จ๋ ์ฌ๋ฐฑ์ ์์ชฝ์ ๋์ผํ๊ฒ ๋ถ๋ฐฐํ๊ธฐ ์ํด ๊ฒฝ๋ก๊ฐ ๋ฐ์ค์ ์ค์์ ์์นํ๊ฒ ํ๋ ์คํ์
์ ๊ณ์ฐํฉ๋๋ค.
const offX = (plotto.SVG_BOX_SIZE - newW) / 2;
const offY = (plotto.SVG_BOX_SIZE - newH) / 2;์ขํ ๋ณํ : ๋ชจ๋ ์ ์ ๋ํด ๋ค์๊ณผ ๊ฐ์ ๋ณํ์ ์ ์ฉํฉ๋๋ค. ์์ ์ด๋: (p.x - minX, p.y - minY), ์ค์ผ์ผ ์ ์ฉ : ๊ณฑํ๊ธฐ s, ์คํ์ ์ ์ฉ : + offX / offY ์ด๋, pen ์ํ๋ ์ ์งํฉ๋๋ค. ์ขํ ๋ณํ ์ดํ, ์ถ๋ ฅ์ขํ๋ ํญ์ 0 ~ SVG_BOX_SIZE ๋ฒ์ ๋ด์ ์์นํฉ๋๋ค.
์ ๊ทํ ๋ points ๊ธฐ์ค(normalizeToBox๋ฅผ ๊ฑฐ์น points ๋ฐฐ์ด ๊ธฐ์ค) ๋ก๋ด ์์ ์ขํ๊ณ๋ก ๋ณํํ๋ ํจ์์ ๋๋ค. SVG ๊ฒฝ๋ก๋ฅผ ๋ก๋ด ํ์ด ๋ฐ๋ผ๊ฐ ์ ๋ ์์น ์ขํ๋ก ๋งคํํฉ๋๋ค.
๋ก๋ด ๊ธฐ์ค์ ๊ณ์ฐ : const home = plotto.fkPenXY_deg(0, 0);์ผ๋ก joint1, joint2๊ฐ ๊ฐ๊ฐ 0๋์ผ ๋, ํ ๋ ์์น๋ฅผ home์ผ๋ก ์ฌ์ฉํฉ๋๋ค. ์ดํ ๋ชจ๋ SVG ์ขํ๋ ์ด ๊ธฐ์ค์ ์ ์๋์ ์ผ๋ก ๋ฐฐ์น๋ฉ๋๋ค.
SVG ์ขํ ์ถ์ถ ๋ฐ ๋ฐ์ ์ฒ๋ฆฌ : filpY === true์ผ ๊ฒฝ์ฐ ๋ก๋ด ์ขํ๊ณ ์ฐจ์ด๋ฅผ ๋ณด์ ํ๊ธฐ ์ํด y์ถ์ ๋ฐ์ ํ๋ฉฐ, u = p.x, v = p.y๋ก ์ขํ๋ฅผ ์ถ์ถํฉ๋๋ค.
๋ก๋ด ์ขํ๊ณ๋ก ๋ณํ : ์ ๊ทํ๋ ๋ฐ์ค ์ขํ์ ์ค์ผ์ผ ๋ณ์ k(ํ์์๋ 1)๋ฅผ ์ ์ฉํ ๋ค, ๊ธฐ์ค์ home์ ๋ํ์ฌ ์ค์ ๋ก๋ด ์ขํ๊ณ๋ก ๋ณํํฉ๋๋ค. ์ด๋, pen์ ์ํ๋ ์ ์งํฉ๋๋ค.
x = home.x + u * k
y = home.y + v * k์ดํ ๋ณํ๋ ๋ฐฐ์ด์ ๋ฐํํฉ๋๋ค.
resamplePathByAngle ํจ์๋ ์ฐ์๋ ๋ ์ ์ฌ์ด์ ๊ด์ ๊ฐ๋ ๋ณํ๊ฐ maxDeltaDeg๋ฅผ ๋์ง ์๋๋ก ์ค๊ฐ ์ ์ ์ฝ์ ํ๋ ํจ์์ ๋๋ค.
์ด๊ธฐํ ๋ฐ ์ฒซ ์ ์ถ๊ฐ : ๊ฒฐ๊ณผ ๋ฆฌ์คํธ result๋ฅผ ์์ฑํ๊ณ , ์ฒซ ์ ์ ๊ทธ๋๋ก ์ถ๊ฐํฉ๋๋ค. ๋ํ, ์ฒซ ์ ์ ์ญ๊ธฐ๊ตฌํ ํด๋ ๋ฏธ๋ฆฌ ๋ณด๊ดํฉ๋๋ค. ์ดํ ๊ฐ ์ธ์ ํ ์ ์(prevPoint, currPoint)์ ๋ํด ๋ ์ ์ ์ญ๊ธฐ๊ตฌํ ๊ฒฐ๊ณผ ๊ฐ๋๋ฅผ ๊ตฌํ ๋ค, ๊ฐ๊ฐ ๋ณํ๋์ ํ์ธํฉ๋๋ค.
์ค๊ฐ ์ ์ฝ์
: ๋ ๊ด์ ์ ๊ฐ๋ ๋ณํ๊ฐ maxDeltaDeg ์ดํ๋ผ๋ฉด ๊ทธ๋๋ก ๋๊ณ , ์๋๋ผ๋ฉด ์ค๊ฐ๊ฐmid์ ์ฝ์
ํฉ๋๋ค.
์ค๊ฐ ์ ์ pen ์ํ๋ ํ์ฌ ์ธ๊ทธ๋จผํธ์ ๋ ์ ๊ณผ ๋์ผํ๊ฒ ์ค์ ํฉ๋๋ค.
mid์ ๋ํด IK๋ฅผ ๊ณ์ฐํ๊ณ , prevPoint -> mid์ mid -> currPoint์ ๋ํด ๋ ๊ตฌ๊ฐ์ ์ฌ๊ท์ ์ผ๋ก ๊ฐ์ ๊ณผ์ ์ ์ ์ฉํฉ๋๋ค.
์ฌ๊ท๋ฅผ ํตํด ๋ถํ ์ด ์๋ฃ๋๋ฉด PrevPoint์์ currPoint์ ์ด๋ฅด๋ ์์ ์ธ๊ทธ๋จผํธ ์ ์ด ์์ฑ๋ฉ๋๋ค.
์ด ๊ฐ ์ธ๊ทธ๋จผํธ์ ์ ์ result์ ์ถ๊ฐํฉ๋๋ค.
์ต์ข
์ ์ผ๋ก result๋ฅผ ๋ฐํํฉ๋๋ค.
-
encodeNibble(d) / decodeNibble(n)
-
์์ฑ๋
motionJson์ ํ๋์จ์ด๋ก ์ ์กํ๊ธฐ ์ํด ์ด์ง ๋ฐ์ดํฐ๋ก ์์ถํฉ๋๋ค. -
Plotto ์ฝ๋์์๋ ๋ ๊ด์ ์ ๋ณํ๋, ์ฆ ฮ ๋ช ๋ น๋ค๊ณผ ํ ์ /๋ค์ด ๋ช ๋ น์ ํจ์จ์ ์ผ๋ก ํํํ๊ธฐ ์ํด ์ปค์คํ ์ธ์ฝ๋ฉ์ ์ฌ์ฉํฉ๋๋ค.
-
์ด๋ ํน์ ๋ฐ์ดํธ ๊ฐ์ ํตํด ํ ๋ช ๋ น๋ค๊ณผ ๊ตฌ๋ถํ๋ฉด์๋, ๋จ 1byte ๋ง์ผ๋ก ํํํ ์ ์์ต๋๋ค. (์์ธํ ๋ด์ฉ์ Plotto Path ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ์ธ์.)
์ฐธ๊ณ : ๋งคํ ํ ์ด๋ธ
$\mathbf{d}$ ๊ฐ (10์ง์)4๋นํธ ์ด์ง์ (Nibble) $\mathbf{d}$ ๊ฐ (10์ง์)4๋นํธ ์ด์ง์ (Nibble) $\mathbf{-7}$ $0b1001$ $\mathbf{0}$ $0b0000$ $\mathbf{-6}$ $0b1010$ $\mathbf{1}$ $0b0001$ $\mathbf{-5}$ $0b1011$ $\mathbf{2}$ $0b0010$ $\mathbf{-4}$ $0b1100$ $\mathbf{3}$ $0b0011$ $\mathbf{-3}$ $0b1101$ $\mathbf{4}$ $0b0100$ $\mathbf{-2}$ $0b1110$ $\mathbf{5}$ $0b0101$ $\mathbf{-1}$ $0b1111$ $\mathbf{6}$ $0b0110$ $\mathbf{7}$ $0b0111$ - Plotto_Path์ ๋ณํ๊ท์น์ ์ํด,
0b1000์ ๋ํ ์ํธ๋ฆฌ๊ฐ ์๋ค๋ ์ ์ ์ฃผ์ํด์ผ ํฉ๋๋ค.encodeNibble์์ ์์ ์์ฑํ์ง ์์ผ๋ฏ๋กdecodeNibble์์๋ ๊ธฐ๋ํ์ง ์์ต๋๋ค.
- encodeNibble(d) : -7 ~ 7 ๋ฒ์์ ์ ์๋ฅผ 4๋นํธ ๊ฐ(0x0~0xF)์ ๋งคํํฉ๋๋ค.
- decodeNibble(n) : 4๋นํธ ๊ฐ์ ๋ค์ -7~7 ์ ์๋ก ๋ณต์ํ๋ ๋งคํ์ ๋๋ค.
-
-
encodeDeltaByte(d1,d2) / decodeDeltaByte(byte)
-
encodeDeltaByte(d1,d2)
- ๋ด๋ถ์ ์ผ๋ก
encodeNibble์ ์ด์ฉํ์ฌ ์์ 4๋นํธ๋ d1์, ํ์ 4๋นํธ๋ d2๋ฅผ ํํํฉ๋๋ค. - ๋ ๊ด์ ์ ฮ์คํ (d1, d2, ๊ฐ๊ฐ -7~7 ๋ฒ์)์ ๋ฐ์ ํ๋์ ๋ฐ์ดํธ ๊ฐ์ผ๋ก ํฉ์นฉ๋๋ค.
- ์: d1=3, d2=-1์ด๋ผ๋ฉด
encodeNibble(3)=0b0011,encodeNibble(-1)=0b1111์ด๋ฏ๋ก
์ต์ข ๊ฐ์0b00111111 (0x3F)์ด ๋ฉ๋๋ค.
- ๋ด๋ถ์ ์ผ๋ก
-
decodeDeltaByte(byte)
- 4๋นํธ ๊ฐ์ ๋ค์ -7~7 ์ ์๋ก ๋ณต์ํ๋ ๋งคํ์ ๋๋ค.
- ๋ฐ์ดํธ๋ฅผ ๋ฐ์ ์์/ํ์ 4๋นํธ๋ฅผ ๊ฐ๊ฐ ์ถ์ถํ๊ณ ,
decodeNibble์ ํตํด
์ ์ ๊ฐ์ผ๋ก ํ์ด๋ธ ํ{ d1: ..., d2: ... }๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
์ด ๋ ํจ์๋ ๊ด์ ๋ฐ ํ ๋ช ๋ น์ ์์ถ/ํด์ ํ๋ ๊ธฐ๋ณธ ๊ตฌ์ฑ ์์์ ๋๋ค.
-
-
plotEncode(motionJson)
-
motionJson๋ฐฐ์ด์ ์ ๋ ฅ์ผ๋ก ๋ฐ์, ๊ฐ ๋ช ๋ น์ ์์ฐจ์ ์ผ๋ก ์ฒ๋ฆฌํ๋ฉด์ ํน์ํ๊ฒ ์ธ์ฝ๋ฉ๋ ๋ฐ์ดํธ ๋ฐฐ์ด์ ์์ฑํฉ๋๋ค.์ฝ๋ ๋ณด๊ธฐ
function plotEncode(motionJson) { const out = []; let prevPen = 0; for (let i = 0; i < motionJson.length; i++) { const cmd = motionJson[i]; const pen = cmd.pen ? 1 : 0; if (pen !== prevPen) { out.push(pen === 1 ? 0x80 : 0x08); prevPen = pen; } out.push(encodeDeltaByte(cmd.d1, cmd.d2)); } return out; }
๋์๋ฐฉ์
-
๊ฒฐ๊ณผ๋ฅผ ์ ์ฅํ ๋น ๋ฐฐ์ด
out์ ์์ฑํ๊ณ , ์ด์ ํ ์ํ๋ฅผ ๋ํ๋ด๋prevPen์0(pen up)์ผ๋ก ์ด๊ธฐํํฉ๋๋ค. -
motionJson๋ฐฐ์ด์ ๊ฐ ๋ช ๋ นcmd๋ฅผ ์์ฐจ์ ์ผ๋ก ์ํํฉ๋๋ค. -
ํ์ฌ ๋ช ๋ น์ ํ ์ํ๋ฅผ ์ซ์ ๊ฐ์ผ๋ก ์ ๊ทํํฉ๋๋ค.
pen = cmd.pen ? 1 : 0
-
ํ์ฌ ํ ์ํ(
pen)์ ์ด์ ํ ์ํ(prevPen)๋ฅผ ๋น๊ตํ์ฌ ํ ์ํ ๋ณํ๊ฐ ์๋์ง ํ์ธํฉ๋๋ค.4-1. ํ ์ํ๊ฐ ๋ณ๊ฒฝ๋์๋ค๋ฉด, ์ํ์ ๋ฐ๋ผ ๋ค์ ๋ช ๋ น ๋ฐ์ดํธ๋ฅผ ์ถ๊ฐํฉ๋๋ค.
- pen up โ pen down :
0x80 - pen down โ pen up :
0x08
- pen up โ pen down :
-
ํ ์ํ ๋ณ๊ฒฝ ๋ช ๋ น์ ๊ธฐ๋กํ ํ,
prevPen์ ํ์ฌ ํ ์ํ๋ก ๊ฐฑ์ ํฉ๋๋ค. -
๋ ๊ด์ ์ ฮ ์ด๋๋
(d1, d2)๋ฅผencodeDeltaByte(d1, d2)๋ฅผ ํตํด ํ๋์ ๋ฐ์ดํธ๋ก ์ธ์ฝ๋ฉํ๊ณ ๊ฒฐ๊ณผ๋ฅผout๋ฐฐ์ด์ ์ถ๊ฐํฉ๋๋ค. -
์ด ฮ ์ด๋ ๋ฐ์ดํธ๋ ์ค์ ์ด๋์ด ์๋ ๊ฒฝ์ฐ์๋ ํญ์ ์ถ๊ฐ๋๋ฉฐ,
(d1, d2) = (0, 0)์ผ ๊ฒฝ์ฐ0x00์ด ๊ธฐ๋ก๋ฉ๋๋ค. -
๋ชจ๋ ๋ช ๋ น์ ์ฒ๋ฆฌํ๋ฉด,
out๋ฐฐ์ด์๋ ํ ์ํ ๋ณํ์ ๊ด์ ์ด๋์ด ์์๋๋ก ๊ธฐ๋ก๋ ๋ฐ์ดํธ ์ํ์ค๊ฐ ์์ฑ๋ฉ๋๋ค. -
์์ฑ๋ ๋ฐ์ดํธ ๋ฐฐ์ด
out์ ๋ฐํํฉ๋๋ค.
-
-
plotDecode(byteArray)
-
plotDecode๋plotEncode์ ์ญ์ผ๋ก, ๋ฐ์ดํธ ๋ฐฐ์ด์ ๋ฐ์ ๋ค์{d1,d2,pen}๋ช ๋ น ๊ฐ์ฒด ๋ฆฌ์คํธ๋ก ๋ณต์ํฉ๋๋ค. - ์ฃผ๋ก ๋๋ฒ๊น ์ด๋ ๊ฒ์ฆ ์ฉ๋๋ก ์ฐ์ผ ์ ์์ต๋๋ค.
์ฝ๋ ๋ณด๊ธฐ
function plotDecode(byteArray) { if (!Array.isArray(byteArray)) { throw new Error("plotDecode: byteArray must be an array"); } const out = []; let pen = 0; for (let i = 0; i < byteArray.length; i++) { const b = byteArray[i]; if (b === 0x80) { pen = 1; } else if (b === 0x08) { pen = 0; } else { const { d1, d2 } = decodeDeltaByte(b); out.push({ d1, d2, pen }); } } return out; }
๋์๋ฐฉ์
-
์ ๋ ฅ ๊ฒ์ฆ
-
byteArray๊ฐ ๋ฐฐ์ด์ธ์ง ํ์ธํฉ๋๋ค. ๊ทธ๋ ์ง ์์ผ๋ฉด ์ค๋ฅ๋ฅผ ๋ฐ์์ํต๋๋ค.
-
-
์ด๊ธฐํ
-
out: ๊ฒฐ๊ณผ ๊ฐ์ฒด ๋ฐฐ์ด -
pen: ํ ์ํ ์ด๊ธฐํ (0: ํ ์ , 1: ํ ๋ค์ด)
-
-
๋ฐฐ์ด ์ํ
-
byteArray์ ๊ฐ ๋ฐ์ดํธ๋ฅผ ์์ฐจ์ ์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค.
-
-
ํ ์ํ ์ฒ๋ฆฌ
-
0x80: ํ ๋ค์ด (pen = 1) -
0x08: ํ ์ (pen = 0)
-
-
ฮ ์ด๋ ๋ช ๋ น ์ฒ๋ฆฌ
-
0x80๋๋0x08์ธ์ ๋ฐ์ดํธ๋ ฮ ์ด๋ ๋ช ๋ น์ ๋๋ค. -
decodeDeltaByte๋ฅผ ์ฌ์ฉํด(d1, d2)๊ฐ์ ๋ณต์ํ๊ณ , ํ์ฌpen์ํ์ ํจ๊ป <>{d1, d2, pen}๊ฐ์ฒด๋ฅผout๋ฐฐ์ด์ ์ถ๊ฐํฉ๋๋ค.
-
-
ํ ์ํ๋ง ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ
-
0x00์d1 = 0,d2 = 0, ํ์ฌ ํ ์ํ๋ก ๋ณต์๋ฉ๋๋ค. - ์ด ๊ฒฝ์ฐ ์ ์๋ฆฌ ์ด๋ ๋ช ๋ น์ผ๋ก ํด์๋ฉ๋๋ค.
-
-
๊ฒฐ๊ณผ ๋ฐํ
- ์ต์ข
์ ์ผ๋ก
{d1, d2, pen}๊ฐ์ฒด๋ค์ ๋ฐฐ์ด์ ๋ฐํํฉ๋๋ค.
- ์ต์ข
์ ์ผ๋ก
-
Plotto ์ฝ๋๋ 2-DOF ํ ๋ก๋ด ํ์ ์ํ ๊ฒฝ๋ก ์์ฑ ๋ฐ ์ ์ด ๋ช ๋ น ์์ฑ๊ธฐ์ ๋๋ค.
์ฌ์ฉ์๋ SVG ํํ๋ก ๊ทธ๋ฆฌ๋ ค๋ ํ์์ ์ ๋ ฅํ๊ณ , ์ฝ๋๋ ์ด๋ฅผ ๋ก๋ด ํ์ ์์ ์์ญ์ ๋ง๊ฒ ์ค์ผ์ผ๋ง ๋ฐ ๋ณํํ์ฌ ์ฐ์๋ ํ ์์ง์ ์ขํ ๋ชฉ๋ก์ ๋ง๋ญ๋๋ค.
์ดํ ๋ก๋ด ํ์ด ์ํํ๊ฒ ์์ง์ผ ์ ์๋๋ก ํด๋น ๊ฒฝ๋ก๋ฅผ ์ธ๋ถํํ๊ณ , ๊ฐ ๊ตฌ๊ฐ์ ๋ํ ๊ด์ ์ ์ธ๋ถ ์คํ ๋ช ๋ น์ ์์ฑํฉ๋๋ค. ๋ง์ง๋ง์ผ๋ก ์ด ๋ช ๋ น๋ค์ ํจ์จ์ ์ธ ๋ฐ์ดํธ ์ฝ๋๋ก ์ธ์ฝ๋ฉํ์ฌ, ์ค์ ์ ์ด ํ๋์จ์ด๋ก ์ฝ๊ฒ ์ ๋ฌ๋ ์ ์๋๋ก ํฉ๋๋ค.
๊ฐ ๊ตฌ์ฑ ์์๋ ๋ค์๊ณผ ๊ฐ์ ์ญํ ์ ๋ด๋นํฉ๋๋ค:
โข ๊ธฐ๊ตฌํ ๊ณ์ฐ (FK & IK): ๋ก๋ด ํ์ ์ขํ โ ๊ด์ ๊ฐ๋ ๋ณํ์ ๋ด๋นํ์ฌ ๊ฒฝ๋ก ์ ์ ๊ด์ ๋ช ๋ น์ผ๋ก ๋ณํํฉ๋๋ค.
โข SVG ๊ฒฝ๋ก ์ฒ๋ฆฌ: ๋ณต์กํ SVG ๋ํ๋ ์ผ๋ จ์ ์ง์ ์ ๋ค๋ก ๋ถํดํ์ฌ ๋ฐ๋ผ๊ฐ ์ ์๊ฒ ํฉ๋๋ค.
โข ๊ฒฝ๋ก ์ต์ ํ (resample): ๊ด์ ์ ๋ฌผ๋ฆฌ์ ์ ์ฝ์ ๊ณ ๋ คํด ๊ฒฝ๋ก๋ฅผ ๋ถ๋๋ฝ๊ณ ์์ ํ๊ฒ ๋ค๋ฌ์ต๋๋ค.
โข ๋ชจ์ JSON ์์ฑ: ์์๋ถํฐ ๋๊น์ง ํ์ ์์ง์๊ณผ ๊ทธ๋ฆผ ๊ทธ๋ฆฌ๊ธฐ ๋์์ ๋ชจ๋ ํฌํจํ ์คํ ๋ช ๋ น ๋ฆฌ์คํธ๋ฅผ ๋ง๋ญ๋๋ค.
โข ๋ช ๋ น ์ธ์ฝ๋ฉ: ์ด ์คํ ๋ช ๋ น ๋ฆฌ์คํธ๋ฅผ ์ต์ํ์ ๋ฐ์ดํฐ๋ก ํํํด ์ ์กํ ์ ์๊ฒ ํฉ๋๋ค.
ํด๋น ์ฝ๋๋ฅผ ์ธ์์ธ๊ณ๋ฐ๋ ๊ฐ๋ฐ์๋ ์ ๋ด์ฉ์ ๋ฐํ์ผ๋ก,
- ๋ก๋ด ํ์ ๋ฌผ๋ฆฌ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์กฐ์ ํ๊ฑฐ๋ ๋ค๋ฅธ ๋ก๋ด์ ์ ์ฉํ ๊ฒฝ์ฐ configure() ๋ถ๋ถ๊ณผ kinematics ๋ถ๋ถ์ ์กฐ์ ํ ์ ์๊ณ ,
- SVG ์ ๋ ฅ์ ๋ฐ๋ผ ๋ก๋ด ์์ง์์ ์์ฑํ๋ ๋ก์ง์ ์ดํดํ์ฌ ํ์ํ ๊ฒฝ์ฐ ์ธ๋ถํ ๋จ๊ณ(MAX_DELTA_DEG ๋ฑ)๋ ์ํ๋ง ๋ฐ๋(samplesPerPath ๋ฑ)๋ฅผ ํ๋ํ ์ ์์ต๋๋ค.
- ๋ํ motionJson๊ณผ plot ๊ฒฐ๊ณผ๋ฅผ ์ด์ฉํด ์ค์ ํ๋์จ์ด ์ ์ด ์ฝ๋์ ์ฐ๋ํ๊ฑฐ๋, ์๋ฎฌ๋ ์ด์ ์์ ์์ง์์ ๊ฒ์ฆํ ์ ์์ต๋๋ค.
ํ์ดํ๋ผ์ธ

- โ๏ธ HW Specification
- ๐งฉ Parsing
- ๐ฃ๏ธ Plotto Path
- ๐ Terminology
- ๐ฅ๏ธ Dashboard UI
- ๐ค Ideas