<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>이상우의 IDL 블로그</title>
    <link>https://swrush.tistory.com/</link>
    <description>과학기술용 프로그래밍 언어 IDL의 다양한 코딩 방법들을 소개하는 블로그입니다. 2026년 4월부터는 새로운 주소(https://blog.naver.com/midikey)로 이전하여 계속 운영중입니다.</description>
    <language>ko</language>
    <pubDate>Mon, 27 Jul 2026 01:12:06 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>이상우_IDL</managingEditor>
    <image>
      <title>이상우의 IDL 블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/5616754/attach/88bfabd99af54841a792fbe93dad27d4</url>
      <link>https://swrush.tistory.com</link>
    </image>
    <item>
      <title>블로그 이전 안내</title>
      <link>https://swrush.tistory.com/notice/836</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이미 안내를 드렸듯이 이 IDL 블로그는 이제 다른 곳으로 이전하여 계속 운영하게 되었습니다. 다만 기존의 이 블로그는 새로운 업데이트만 없을 뿐 기존에 이미 올라와있던 게시물들은 그대로 유지될 것입니다. 새로운 블로그의 주소는 아래와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://blog.naver.com/midikey&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.naver.com/midikey&lt;/a&gt;&lt;/p&gt;</description>
      <author>이상우_IDL</author>
      <guid isPermaLink="true">https://swrush.tistory.com/notice/836</guid>
      <pubDate>Tue, 7 Apr 2026 15:30:37 +0900</pubDate>
    </item>
    <item>
      <title>블로그 이전 안내 드립니다</title>
      <link>https://swrush.tistory.com/835</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 이 블로그에 방문해주시는 이용자 여러분들께 항상 감사드린다는 말씀을 드리고 싶습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다름이 아니라 제가 운영중인 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;이 IDL 블로그를 이제 다른 곳으로 이전하기로 결정&lt;/b&gt;&lt;/span&gt;하게 되어서 이에 관한 안내 말씀을 드리고자 합니다. 제가 이 블로그를 시작한 시기가 2010년경이었으므로 이제 대략 16년 정도가 흘렀습니다. 이 블로그를 운영하게 된 취지는 국내 IDL 사용자들께 여러가지 기술적 도움을 드리고자 하는 마음이었습니다. 사실 국내에서는 IDL의 사용자 저변이 그리 넓은 편은 아니기 때문에 다른 프로그래밍 언어들처럼 유저 커뮤니티의 활동이 활발하지는 않습니다. 그렇기 때문에 IDL 도움말과 같은 교과서적이고 백과사전적인 내용 이외에 유저들이 실제로 겪게 되는 기술적 난관이나 의문들을 해소할만한 창구가 충분하지 않은 것도 사실입니다. 따라서 나름 IDL 코딩을 오랜 세월 동안 해온 유저의 한 사람으로서 다른 IDL 유저들의 그러한 갈증을 완벽하게는 아니더라도 어느 정도까지만이라도 보듬어드릴 수 있는 역할을 해보자는 차원에서 이 블로그를 개설하고 운영해오고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 IDL이 오랜 세월 동안 과학기술 분야에서 널리 사용되고 많은 기여를 해온 프로그래밍 언어이긴 하지만, IT 업계 전체적인 관점에서 볼 때에는 그 비중은 작은 편입니다. 더구나 이미 오래전부터 파이썬(Python) 등과 같은 다른 대체제들이 넘쳐나기 시작하면서 그 입지는 점점 더 좁아지고 있고, 이제는 AI 시대를 맞아서 사람이 코딩을 일일이 하는 것의 의미에 대한 의문까지도 생겨나는 시점이기도 합니다. 그래서 IDL 코딩을 오랜 시간 동안 해왔던 저도 여러모로 마음이 복잡해지기도 하고, 과연 이 블로그를 계속 운영하는 것이 계속 의미가 있을 것인가에 대한 근본적 의문이 드는 경우도 종종 있습니다. 하지만 IDL 유저들은 여전히 존재하고 그 분들에게 계속 도움이 되었으면 하는 바램은 저도 항상 갖고 있기 때문에 향후에도 힘 닿는데까지는 지속적으로 운영을 할 생각입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 제 입장에서도 뭔가 소소한 전환점같은 것이 필요할 것 같아서 블로그를 다른 곳으로 이전하기로 결심하였습니다. 물론 이유는 몇가지 더 있긴 합니다만 여기서 구체적으로 일일이 다 언급할 필요는 없을 것 같습니다. 새로 이전할 곳은 네이버 블로그입니다. 얼마전부터 준비를 해오고 있었고 이제는 거의 완료되어가는 상태입니다. 그래서 이 블로그에서는 새로운 게시물의 업데이트는 더 이상 진행되지 않을 것이고 이제부터는&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&amp;nbsp;네이버 블로그로 이전하여 계속 운영할 예정&lt;/b&gt;&lt;/span&gt;입니다. 그리고 &lt;b&gt;기존의 이 블로그는 삭제하거나 폐쇄하지 않고 그대로 유지될 예정&lt;/b&gt;입니다. 이미 올라와있는 게시물들은 그대로 유산(Legacy)으로 계속 남겨둘 것입니다. 따라서 기존 블로그의 내용을 보시는 것은 아무 지장이 없을 것이라는 것을 말씀드립니다. 다만 이제부터는 새로운 블로그에서 새로운 내용들이 게제될 것입니다. 새로운 블로그의 링크는 아래와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;a href=&quot;https://blog.naver.com/midikey&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://blog.naver.com/midikey&lt;/a&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 블로그는 현재 여러가지 셋업을 하는 중이기 때문에 현재의 모습은 아직은 과도기이긴 하지만 이제 정상적으로 새로운 게시물들이 올라갈 예정입니다. 다소 갑작스럽게 느껴지실 수도 있겠지만 저도 오랜 시간 고민끝에 내린 결정이라는 점 양해 부탁드립니다. 지금까지 이 IDL 블로그를 이용해주셨던 분들께 다시 한번 감사드리며, 새로운 IDL 블로그에 대해서도 변함없는 관심과 방문 부탁드려봅니다. 감사합니다.&lt;/p&gt;</description>
      <category>IDL/General</category>
      <author>이상우_IDL</author>
      <guid isPermaLink="true">https://swrush.tistory.com/835</guid>
      <comments>https://swrush.tistory.com/835#entry835comment</comments>
      <pubDate>Tue, 7 Apr 2026 15:00:13 +0900</pubDate>
    </item>
    <item>
      <title>웨비나(Webinar) 안내 (2026. 4. 15)</title>
      <link>https://swrush.tistory.com/833</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;IDL/ENVI의 제작사인 NV5 Geospatial에서 오는 4월 15일에서 4월 16일에 걸쳐 개최될 예정인 웨비나(Webinar)에 대하여 안내합니다. 이번 웨비나의 제목은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&quot;Meet Your New Partners in Science: ENVI Agent and IDL Agent&quot;&lt;/b&gt;&lt;/span&gt;입니다. 이번 웨비나에서는 최근에 &lt;b&gt;ENVI와 IDL에 도입된 Agent 기능&lt;/b&gt;을 중점적으로 소개하게 됩니다. 이것은 &lt;b&gt;작업의 도우미 역할을 하는 AI 기능&lt;/b&gt;이라고 보시면 됩니다. 요즘 워낙에 AI 시대이기도 하고 다양한 분야에 걸쳐서 AI의 기능이 이용되고 있는데, IDL에서도 코딩의 보조 역할을 하는 IDL Agent 기능이 도입된 셈입니다. 일단 이 기능을 사용하기 위해서는 다음과 같은 조건이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;&amp;bull;&lt;/span&gt; IDL 9.2의 설치 및 라이센싱&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;&amp;bull;&lt;/span&gt; VSC(Visual Studio Code) 최신 버전 설치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;&amp;bull;&lt;/span&gt; VSC에 추가 extension으로 IDL for VSCode 설치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;&amp;bull;&lt;/span&gt; VSC에 추가 extension으로 Github Copilot Chat 설치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;&amp;bull;&lt;/span&gt; Github Copilot Pro 멤버쉽 가입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 이상과 같은 과정들이 충족되어야 IDL Agent의 기능을 제대로 사용할 수 있습니다. 마지막에 언급된 Github Copile 멤버쉽의 경우는 무료 및 30일 트라이얼도 가능하지만 지속적인 사용을 위해서는 유료 멤버쉽 가입이 필요하다고 합니다. 어쨌든 저도 이러한 준비 과정들을 거쳐서 간단하게 사용을 해보고 있는 중입니니다. 일단 참고할만한 간단한 사용 후기는 아래 링크를 통하여 보실 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://groups.google.com/g/idl_envi_korea/c/cs2AGFi0XeA&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크 누르기&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이번 웨비나의 경우도 항상 그래왔듯이 각 대륙별 시간대에 맞춰서 동일한 내용으로 총 3회 진행됩니다. 각각의 시작 시간은 한국시간(KST)으로는 4월 15일 09시, 4월 15일 23시, 4월 16일 02시입니다. 물론 NV5 Geospatial에서 직접 주관하는 이벤트이기 때문에 영어로 진행됩니다. 이번 웨비나의 내용 조회 및 참가 신청이 가능한 웹페이지는 아래 링크와 같습니다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&lt;a href=&quot;https://www.nv5geospatialsoftware.com/Company/Events/Events-Detail/meet-your-new-partners-in-science-envi-agent-and-idl-agent&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;웨비나 참가 신청&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;물론 웨비나의 영상 및 내용은 나중에도 볼 수 있게 공개되기 때문에 웨비나에 꼭 실시간으로 참석하지 않더라도 정보를 얻는데 있어서 아무런 지장은 없습니다. 이번 웨비나에서 소개될 내용에 관하여 공유해볼만한 것이 있다면 저도 웨비나 이후에 따로 정리하여 이 블로그를 통하여 소개할 예정입니다.&lt;/p&gt;</description>
      <category>IDL/General</category>
      <author>이상우_IDL</author>
      <guid isPermaLink="true">https://swrush.tistory.com/833</guid>
      <comments>https://swrush.tistory.com/833#entry833comment</comments>
      <pubDate>Thu, 2 Apr 2026 14:05:53 +0900</pubDate>
    </item>
    <item>
      <title>궤적 상의 입자 운동 구현 및 애니메이션 (3D)</title>
      <link>https://swrush.tistory.com/832</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;2차원 공간에 존재하는 궤적이 있고 그 위에서 움직이는 입자가 있는 상황을 가정하여 이를 그래픽적으로 도식화하고 그 움직임을 담은 애니메이션 파일을 만들어보는 예제를 소개하는 &lt;a href=&quot;https://swrush.tistory.com/831&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;게시물&lt;/a&gt;을 얼마전에 올린 바 있습니다. 이번에는 2차원 대신 3차원 공간에 대한 예제를 살펴보고자 합니다. 즉 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;3차원 공간에 존재하는 궤적이 있고 그 위에서 움직이는 입자가 있는 상황&lt;/b&gt;&lt;/span&gt;을 가정하여 이를 &lt;b&gt;그래픽적으로 도식화하고 그 움직임을 담은 애니메이션 파일을 만들어보는 예제&lt;/b&gt;를 소개해보기로 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 전반적인 내용의 흐름 자체는 2차원 예제와 크게 다르지는 않습니다. 다만 모든 것이 3차원이 구현된다는 부분만 다를 뿐입니다. 그러면 3차원 공간상에 존재하는 궤적을 구성하는 점들의 좌표 데이터를 생성하는 작업부터 진행해야 하는데요. 여기서는 &lt;b&gt;3차원 공간상에 존재하는 원형 궤적&lt;/b&gt;을 예제로 사용해보고자 합니다. 이를 위해서는 관련된 이론적인 수식을 이용해야 하는데 아무래도 3차원 버전이다보니 수식 자체는 약간 복잡합니다. 어쨌든 이러한 수식을 사용하여 데이터를 생성하는 과정은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n&amp;nbsp;=&amp;nbsp;400 &lt;br /&gt;t&amp;nbsp;=&amp;nbsp;[0:2*!pi:2*!pi/n] &lt;br /&gt;a&amp;nbsp;=&amp;nbsp;7. &lt;br /&gt;b&amp;nbsp;=&amp;nbsp;6. &lt;br /&gt;c&amp;nbsp;=&amp;nbsp;5. &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;6. &lt;br /&gt;x&amp;nbsp;=&amp;nbsp;r/SQRT(a^2+b^2)*(b*COS(t)+a*c*SIN(t)/SQRT(a^2+b^2+c^2)) &lt;br /&gt;y&amp;nbsp;=&amp;nbsp;r/SQRT(a^2+b^2)*(-a*COS(t)+b*c*SIN(t)/SQRT(a^2+b^2+c^2)) &lt;br /&gt;z&amp;nbsp;=&amp;nbsp;r/SQRT(a^2+b^2)*(-(a^2+b^2)*SIN(t))/SQRT(a^2+b^2+c^2) &lt;br /&gt;HELP,&amp;nbsp;x,&amp;nbsp;y,&amp;nbsp;z&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 &lt;b&gt;ax+by+cz=0에 해당되는 평면상에 존재하며 중심 좌표가 (0, 0, 0)이고 반경이 r인 원형 궤적&lt;/b&gt;을 구성하는 좌표값들로 구성된 x, y, z를 정의한 것입니다. 물론 x, y, z는 각각 X축, Y축, Z축 방향의 좌표값들인데 여기서는 각각 400개의 실수형 값들로 구성된 배열이 됩니다. 이제 이러한 점들로 구성된 궤적을 그림으로 표출하는 작업을 해야 하는데 이를 위해서는 &lt;b&gt;PLOT3D 함수&lt;/b&gt;를 사용하기로 합니다. 그 과정은 대략 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sx&amp;nbsp;=&amp;nbsp;600 &lt;br /&gt;sy&amp;nbsp;=&amp;nbsp;600 &lt;br /&gt;win&amp;nbsp;=&amp;nbsp;WINDOW(DIMENSIONS=[sx,&amp;nbsp;sy],&amp;nbsp;/NO_TOOLBAR) &lt;br /&gt;p = PLOT3D(x, y, z, COLOR='green', THICK=2, ASPECT_Z=1, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; AXIS_STYLE=2, FONT_SIZE=11, MARGIN=0.2, /CURRENT)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 이와 같은 내용을 실행하면 3차원 공간상에 궤적이 표시됩니다. 그 모습을 보면 다음 그림과 같습니다. 그냥 보기엔 마치 타원처럼 보일 수 있지만, 원형 궤적의 평면이 기울어져있어서 그렇게 보이는 것 뿐입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260316_motion_on_curve_1a.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2SCKe/dJMcaaEJ2YV/MA2eWmqHmQYBJLLJfWq36k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2SCKe/dJMcaaEJ2YV/MA2eWmqHmQYBJLLJfWq36k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2SCKe/dJMcaaEJ2YV/MA2eWmqHmQYBJLLJfWq36k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2SCKe%2FdJMcaaEJ2YV%2FMA2eWmqHmQYBJLLJfWq36k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260316_motion_on_curve_1a.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 궤적을 구성하는 점들 중 첫번째 점인 x[0], y[0], z[0]의 위치에 3차원 구체를 삽입하고자 합니다. 즉 3차원적인 구형의 그래픽 개체를 추가하려는 것인데, 지난번 2차원 버전에서는 이를 SYMBOL 함수로 처리한 바 있습니다. 하지만 여기서 &lt;b&gt;3차원적인 구체를 추가&lt;/b&gt;하려면 SYMBOL 함수 대신 &lt;b&gt;SCATTERPLOT3D 함수&lt;/b&gt;를 사용해야 합니다. 그 내용은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sym = SCATTERPLOT3D(x[0], y[0], z[0], SYM_OBJECT=orb(), $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; SYM_SIZE=3, SYM_COLOR='red', /OVERPLOT)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 SCATTERPLOT3D 함수를 사용해야 하는 이유는 3차원 구체를 삽입하기 위하여 사용되는 &lt;b&gt;SYM_OBJECT 속성&lt;/b&gt;이 SYMBOL 함수에서는 지원되지 않기 때문입니다. 어쨌든 위의 내용까지 추가로 실행되면 그 결과는 다음 그림과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260316_motion_on_curve_1b.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQyEgN/dJMcagLIMWt/sBTELHyg5VbOt6E8w68mS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQyEgN/dJMcagLIMWt/sBTELHyg5VbOt6E8w68mS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQyEgN/dJMcagLIMWt/sBTELHyg5VbOt6E8w68mS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQyEgN%2FdJMcagLIMWt%2FsBTELHyg5VbOt6E8w68mS0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260316_motion_on_curve_1b.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 위와 같이 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;삽입된 구체가 궤적을 따라 움직이도록&lt;/b&gt;&lt;/span&gt; 해봅시다. 이를 위해서는 방금 삽입했던 &lt;b&gt;구체의 위치 좌표가 순차적으로 변화하도록&lt;/b&gt; 해줘야 합니다. 이러한 처리는 &lt;b&gt;구체에 대하여 SetData 메서드를 사용&lt;/b&gt;하면서 이를 반복형 구문 내에서 순차적으로 실행되도록 하면 됩니다. 그 내용은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FOR j = 0, n DO sym.SetData, x[j], y[j], z[j]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같은 내용까지 실행하면 그래픽 창에 표출된 그림 내에서 구체가 궤적을 따라 순차적으로 이동하는 모습을 볼 수 있을 것입니다. 물론 이러한 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;움직임을 애니메이션으로 담은 파일을 제작&lt;/b&gt;&lt;/span&gt;하는 것 필요할 것 같습니다. 그러면 &lt;b&gt;애니메이션 GIF 파일&lt;/b&gt;로 만들기 위하여 바로 위의 반복형 구문의 내용을 다음과 같이 수정해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wfile = 'motion_on_curve_3d.gif' &lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;n&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;sym.SetData,&amp;nbsp;x[j],&amp;nbsp;y[j],&amp;nbsp;z[j] &lt;br /&gt;&amp;nbsp; cap = win.CopyWindow(WIDTH=sx) &lt;br /&gt;&amp;nbsp; frame = COLOR_QUAN(cap, 1, r, g, b) &lt;br /&gt;&amp;nbsp; WRITE_GIF, wfile, frame, r, g, b, /MULTIPLE, $ &lt;br /&gt;&amp;nbsp; &amp;nbsp; DELAY_TIME=2, REPEAT_COUNT=0 &lt;br /&gt;ENDFOR &lt;br /&gt;WRITE_GIF, wfile, /CLOSE&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 애니메이션 GIF 파일로 만드는 세부적인 방법에 관해서는 관련 게시물의 내용을 참조하시면 됩니다. 이 작업이 모두 끝나면 motion_on_curve_3d.gif라는 이름의 애니메이션 GIF 파일이 생성될 것입니다. 이 파일은 아래에 첨부하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260316_motion_on_curve_1.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1v42I/dJMcajarTKw/9Zr9mKD1q8dg4KpGOGhkw1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1v42I/dJMcajarTKw/9Zr9mKD1q8dg4KpGOGhkw1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1v42I/dJMcajarTKw/9Zr9mKD1q8dg4KpGOGhkw1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/b1v42I/dJMcajarTKw/9Zr9mKD1q8dg4KpGOGhkw1/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260316_motion_on_curve_1.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 작업을 좀 더 확대해서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;궤적과 구체를 하나 더 삽입하여 두 종류의 궤적 및 구체를 구현&lt;/b&gt;&lt;/span&gt;해보는 것은 어떨까 합니다. 이를 위해서는 당연히 두 종류의 데이터가 필요하므로 앞선 내용을 참조하여 다음과 같이 시작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n&amp;nbsp;=&amp;nbsp;400 &lt;br /&gt;t&amp;nbsp;=&amp;nbsp;[0:2*!pi:2*!pi/n] &lt;br /&gt;a&amp;nbsp;=&amp;nbsp;7. &lt;br /&gt;b&amp;nbsp;=&amp;nbsp;6. &lt;br /&gt;c&amp;nbsp;=&amp;nbsp;5. &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;6. &lt;br /&gt;x1&amp;nbsp;=&amp;nbsp;r/SQRT(a^2+b^2)*(b*COS(t)+a*c*SIN(t)/SQRT(a^2+b^2+c^2)) &lt;br /&gt;y1&amp;nbsp;=&amp;nbsp;r/SQRT(a^2+b^2)*(-a*COS(t)+b*c*SIN(t)/SQRT(a^2+b^2+c^2)) &lt;br /&gt;z1&amp;nbsp;=&amp;nbsp;r/SQRT(a^2+b^2)*(-(a^2+b^2)*SIN(t))/SQRT(a^2+b^2+c^2) &lt;br /&gt;a&amp;nbsp;=&amp;nbsp;2. &lt;br /&gt;b&amp;nbsp;=&amp;nbsp;8. &lt;br /&gt;c&amp;nbsp;=&amp;nbsp;3. &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;9. &lt;br /&gt;x2&amp;nbsp;=&amp;nbsp;r/SQRT(a^2+b^2)*(b*COS(t)+a*c*SIN(t)/SQRT(a^2+b^2+c^2)) &lt;br /&gt;y2&amp;nbsp;=&amp;nbsp;r/SQRT(a^2+b^2)*(-a*COS(t)+b*c*SIN(t)/SQRT(a^2+b^2+c^2)) &lt;br /&gt;z2&amp;nbsp;=&amp;nbsp;r/SQRT(a^2+b^2)*(-(a^2+b^2)*SIN(t))/SQRT(a^2+b^2+c^2) &lt;br /&gt;HELP,&amp;nbsp;x1,&amp;nbsp;y1,&amp;nbsp;z1,&amp;nbsp;x2,&amp;nbsp;y2,&amp;nbsp;z2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 &lt;b&gt;궤도 평면 및 반경이 서로 다른 두 종류의 궤적 데이터를 정의&lt;/b&gt;하였습니다. 이어지는 표출 과정은 앞선 예제와 거의 유사합니다. 표시할 그래픽 개체들이 두 종류가 되었다는 차이만 고려하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sx&amp;nbsp;=&amp;nbsp;600 &lt;br /&gt;sy&amp;nbsp;=&amp;nbsp;600 &lt;br /&gt;win&amp;nbsp;=&amp;nbsp;WINDOW(DIMENSIONS=[sx,&amp;nbsp;sy],&amp;nbsp;/NO_TOOLBAR) &lt;br /&gt;p1&amp;nbsp;=&amp;nbsp;PLOT3D(x1,&amp;nbsp;y1,&amp;nbsp;z1,&amp;nbsp;COLOR='green',&amp;nbsp;THICK=2,&amp;nbsp;ASPECT_Z=1,&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;XRANGE=[-10,&amp;nbsp;10],&amp;nbsp;YRANGE=[-10,&amp;nbsp;10],&amp;nbsp;ZRANGE=[-10,&amp;nbsp;10],&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;AXIS_STYLE=2,&amp;nbsp;FONT_SIZE=11,&amp;nbsp;MARGIN=0.2,&amp;nbsp;/CURRENT) &lt;br /&gt;sym1 = SCATTERPLOT3D(x1[0], y1[0], z1[0], SYM_OBJECT=orb(), $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; SYM_SIZE=3, SYM_COLOR='red', /OVERPLOT) &lt;br /&gt;p2&amp;nbsp;=&amp;nbsp;PLOT3D(x2,&amp;nbsp;y2,&amp;nbsp;z2,&amp;nbsp;COLOR='blue',&amp;nbsp;THICK=2,&amp;nbsp;ASPECT_Z=1,&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;AXIS_STYLE=2,&amp;nbsp;FONT_SIZE=11,&amp;nbsp;MARGIN=0.2,&amp;nbsp;/OVERPLOT) &lt;br /&gt;sym2 = SCATTERPLOT3D(x2[0], y2[0], z2[0], SYM_OBJECT=orb(), $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; SYM_SIZE=4, SYM_COLOR='aqua', /OVERPLOT)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 두 종류의 데이터에 해당되는 궤적 및 구체를 모두 표시하기 위하여 &lt;b&gt;PLOT3D 함수 및 SCATTERPLOT3D 함수&lt;/b&gt;가 각각 두번씩 사용되었습니다. 표출된 그림을 보면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260316_motion_on_curve_2.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K3JtH/dJMcajhjs8T/NyC76dZKuSfwfXfs9m8npK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K3JtH/dJMcajhjs8T/NyC76dZKuSfwfXfs9m8npK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K3JtH/dJMcajhjs8T/NyC76dZKuSfwfXfs9m8npK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK3JtH%2FdJMcajhjs8T%2FNyC76dZKuSfwfXfs9m8npK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260316_motion_on_curve_2.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음은 &lt;b&gt;삽입된 구체들이 각자의 궤도상에서 움직이도록&lt;/b&gt; 하는 작업입니다. 요령은 앞선 예제와 비슷하며 단지 구체 하나가 더 추가되었다는 점만 다를 뿐입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;n&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;sym1.SetData,&amp;nbsp;x1[j],&amp;nbsp;y1[j],&amp;nbsp;z1[j] &lt;br /&gt;&amp;nbsp;&amp;nbsp;sym2.SetData,&amp;nbsp;x2[j],&amp;nbsp;y2[j],&amp;nbsp;z2[j] &lt;br /&gt;ENDFOR&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같은 내용을 실행하면 그래픽 창에 표출된 그림 내에서 구체가 궤적을 따라 순차적으로 이동하는 모습을 볼 수 있게 됩니다. 이제 이 모습을 애니메이션 GIF 파일로 만들기 위하여 위의 내용을 다음과 같이 수정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wfile = 'motion_on_curve_3d.gif' &lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;n&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;sym1.SetData,&amp;nbsp;x1[j],&amp;nbsp;y1[j],&amp;nbsp;z1[j] &lt;br /&gt;&amp;nbsp;&amp;nbsp;sym2.SetData,&amp;nbsp;x2[j],&amp;nbsp;y2[j],&amp;nbsp;z2[j] &lt;br /&gt;&amp;nbsp; cap = win.CopyWindow(WIDTH=sx) &lt;br /&gt;&amp;nbsp; frame = COLOR_QUAN(cap, 1, r, g, b) &lt;br /&gt;&amp;nbsp; WRITE_GIF, wfile, frame, r, g, b, /MULTIPLE, $ &lt;br /&gt;&amp;nbsp; &amp;nbsp; DELAY_TIME=2, REPEAT_COUNT=0 &lt;br /&gt;ENDFOR &lt;br /&gt;WRITE_GIF, wfile, /CLOSE&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 작업이 모두 끝나면 motion_on_curve_3d.gif라는 이름의 애니메이션 GIF 파일이 생성될 것입니다. 이 파일은 아래에 첨부하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260316_motion_on_curve_2.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HagK5/dJMcafTteCP/pA7AZ9Ul9fUYlHhJifIVF0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HagK5/dJMcafTteCP/pA7AZ9Ul9fUYlHhJifIVF0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HagK5/dJMcafTteCP/pA7AZ9Ul9fUYlHhJifIVF0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/HagK5/dJMcafTteCP/pA7AZ9Ul9fUYlHhJifIVF0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260316_motion_on_curve_2.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 소개된 두가지 예제들에서는 애니메이션을 담은 파일을 GIF 형식으로 만들었는데, MP4 형식의 동영상 파일로 만드는 것도 물론 가능합니다. 그 방법은 앞서 2차원 공간 버전에 대한 내용을 담은 &lt;a href=&quot;https://swrush.tistory.com/831&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;게시물&lt;/a&gt;에서 소개된 것과 동일하며 여기서는 생략하기로 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;* 이 글이 도움이 되었다면 게시물에 대하여 공감 버튼(하트 모양) 클릭 및 블로그 구독도 해주시면 더 큰 힘이 됩니다. 감사합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IDL/New Graphics</category>
      <author>이상우_IDL</author>
      <guid isPermaLink="true">https://swrush.tistory.com/832</guid>
      <comments>https://swrush.tistory.com/832#entry832comment</comments>
      <pubDate>Tue, 31 Mar 2026 16:16:11 +0900</pubDate>
    </item>
    <item>
      <title>이미지의 부분 영역 확대 표출 및 애니메이션</title>
      <link>https://swrush.tistory.com/829</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 이미지를 처리 및 표출하는 예제로서, 사이즈가 큰 이미지 데이터가 주어졌을 때 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;원본 이미지와 그 중 일부에 해당되는 영역만 확대된 부분 이미지를 나란히 배치하고 그 대상이 되는 영역의 위치를 순차적으로 변화&lt;/b&gt;&lt;/span&gt;시키는 예제를 살펴보고자 합니다. 예제로 사용할 이미지 데이터는 IDL의 설치 폴더에서 제공되는 boulder.tif라는 파일을 읽어서 배열로 가져오기로 합니다. 이 파일은 TIFF 형식이며 다음과 같이 READ_IMAGE 함수를 사용하여 읽으면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;file&amp;nbsp;=&amp;nbsp;FILEPATH('boulder.tif',&amp;nbsp;SUBDIRECTORY=['examples',&amp;nbsp;'data']) &lt;br /&gt;data&amp;nbsp;=&amp;nbsp;READ_IMAGE(file) &lt;br /&gt;HELP,&amp;nbsp;data&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 데이터를 읽으면 1071x1390의 크기를 갖는 바이트형 배열인 data를 얻게 됩니다. 이제 그래픽 창을 띄우고 표출을 해야 하는데, 이번 작업에서는 가로 방향으로 긴 그래픽 창을 띄우고 &lt;b&gt;왼쪽에는 원본 이미지를 그리고 오른쪽에는 부분 영역을 확대한 이미지를 표시&lt;/b&gt;하기로 합니다. 그 과정은 다음과 같이 시작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sx&amp;nbsp;=&amp;nbsp;1000 &lt;br /&gt;sy&amp;nbsp;=&amp;nbsp;500 &lt;br /&gt;win&amp;nbsp;=&amp;nbsp;WINDOW(DIMENSIONS=[sx,&amp;nbsp;sy],&amp;nbsp;/NO_TOOLBAR) &lt;br /&gt;i0&amp;nbsp;=&amp;nbsp;IMAGE(data,&amp;nbsp;MARGIN=0.02,&amp;nbsp;/CURRENT,&amp;nbsp;LAYOUT=[2,&amp;nbsp;1,&amp;nbsp;1]) &lt;br /&gt;bszx&amp;nbsp;=&amp;nbsp;200 &lt;br /&gt;bszy&amp;nbsp;=&amp;nbsp;200 &lt;br /&gt;bpx&amp;nbsp;=&amp;nbsp;100 &lt;br /&gt;bpy&amp;nbsp;=&amp;nbsp;1100 &lt;br /&gt;box&amp;nbsp;=&amp;nbsp;POLYGON([bpx,&amp;nbsp;bpx+bszx,&amp;nbsp;bpx+bszx,&amp;nbsp;bpx],&amp;nbsp;[bpy,&amp;nbsp;bpy,&amp;nbsp;bpy+bszy,&amp;nbsp;bpy+bszy],&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;FILL_BACKGROUND=0,&amp;nbsp;COLOR='yellow',&amp;nbsp;THICK=2,&amp;nbsp;/DATA)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 1000x500 크기의 그래픽 창을 띄우고 왼쪽 섹션에 원본 이미지 데이터인 data를 표출하였습니다. 그리고 POLYGON 함수를 사용하여 노란색 윤곽선의 박스를 삽입하였는데, 이것은 나중에 확대하게 될 부분 영역의 위치를 표시하기 위해서입니다. 여기서는 X 방향으로 100~299 그리고 Y 방향으로 1100~1299의 좌표 범위에 해당되는 200x200 크기의 부분 영역을 정의하였습니다. 그 다음에는 이 부분 영역에 해당되는 부분 배열을 추출하여 부분 이미지를 그래픽 창의 오른쪽에 표시하기 위하여 다음과 같은 과정을 추가합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;img&amp;nbsp;=&amp;nbsp;data[bpx:bpx+bszx,&amp;nbsp;bpy:bpy+bszy] &lt;br /&gt;i1 = IMAGE(img, MARGIN=0.02, /CURRENT, LAYOUT=[2, 1, 2])&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 부분 이미지에 해당되는 배열 img를 얻고 이를 이미지의 형태로 오른쪽에 표출하는 과정까지 실행하면 표출 결과는 다음그림과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260219_image_zoom_1a.png&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBswGV/dJMcafr65PJ/aB8RVLlmCqqhkwTLTPHQ3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBswGV/dJMcafr65PJ/aB8RVLlmCqqhkwTLTPHQ3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBswGV/dJMcafr65PJ/aB8RVLlmCqqhkwTLTPHQ3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBswGV%2FdJMcafr65PJ%2FaB8RVLlmCqqhkwTLTPHQ3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1000&quot; height=&quot;500&quot; data-filename=&quot;20260219_image_zoom_1a.png&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 여기서는 부분 이미지의 크기가 200x200인데 표출될 그래픽 창은 더 크기 때문에 자연스럽게 확대된 모습으로 보이게 됩니다. 다만 확대된 이미지를 보면 픽셀들이 계단처럼 보이는데 이것은 이미지가 확대될 때 적용되는 디폴트 기법이 샘플링(Nearest Neighbor Sampling)이기 때문입니다. 만약 좀 더 부드러운 확대 이미지가 되도록 하려면 &lt;b&gt;IMAGE 함수에서 INTERPOLATE 속성을 1로 설정하여 2차원 선형 내삽(Bilinear Interpolation) 기법이 적용되도록&lt;/b&gt; 하면 됩니다. 즉 바로 위에서 IMAGE 함수가 사용되었던 내용을 다음과 같이 변경하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;i1&amp;nbsp;=&amp;nbsp;IMAGE(img,&amp;nbsp;&lt;b&gt;INTERPOLATE=1&lt;/b&gt;,&amp;nbsp;MARGIN=0.02,&amp;nbsp;/CURRENT,&amp;nbsp;LAYOUT=[2,&amp;nbsp;1,&amp;nbsp;2])&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 표출 결과는 다음과 같습니다. 이제는 확대 이미지에서 픽셀들이 거칠게 보이지 않고 부드럽게 보이게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260219_image_zoom_1b.png&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lUJdt/dJMcaf6IIRV/HcxRu7sFkRTN3G4rK1psVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lUJdt/dJMcaf6IIRV/HcxRu7sFkRTN3G4rK1psVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lUJdt/dJMcaf6IIRV/HcxRu7sFkRTN3G4rK1psVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlUJdt%2FdJMcaf6IIRV%2FHcxRu7sFkRTN3G4rK1psVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1000&quot; height=&quot;500&quot; data-filename=&quot;20260219_image_zoom_1b.png&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 원본 이미지 및 확대 이미지는 이렇게 표시되도록 하고 다음 단계로 가서 부분 영역의 위치를 순차적으로 변경해봅시다. 즉 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;부분 영역의 위치가 순차적으로 변화하면서 왼쪽의 영역 박스 및 오른쪽의 확대 이미지도 함께 연동되어 변화하도록&lt;/b&gt;&lt;/span&gt; 해보려는 것입니다. 이를 위해서는 &lt;b&gt;반복형 구문&lt;/b&gt;을 사용해야 합니다. 그러면서 박스 및 확대 이미지의 속성을 변화시키기 위하여 각 개체에 대하여 &lt;b&gt;SetData 메서드&lt;/b&gt;를 사용하면 됩니다. 그 과정은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FOR j = 0, 360 DO BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;box.SetData,&amp;nbsp;[bpx,&amp;nbsp;bpx+bszx,&amp;nbsp;bpx+bszx,&amp;nbsp;bpx]+j,&amp;nbsp;[bpy,&amp;nbsp;bpy,&amp;nbsp;bpy+bszy,&amp;nbsp;bpy+bszy] &lt;br /&gt;&amp;nbsp;&amp;nbsp;i1.SetData,&amp;nbsp;data[bpx+j:bpx+bszx+j,&amp;nbsp;bpy:bpy+bszy] &lt;br /&gt;ENDFOR&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 &lt;b&gt;부분 영역을 X축 방향으로 처음 위치로부터 1 픽셀씩 360회에 걸쳐 이동&lt;/b&gt;시켜본 것입니다. 그러면서 박스의 위치 좌표를 변화시키는 작업 및 부분 영역의 범위를 변화시키는 작업을 위하여 각각의 그래픽 개체인 box, i1에 대하여 SetData 메서드를 사용한 것을 주목하면 됩니다. 이러한 내용을 실행하면 그래픽 창이 뜬 상태에서 박스의 위치 및 확대 이미지가 순차적으로 변화하는 모습을 볼 수 있게 됩니다. 그 모습은 여러분이 IDL에서 직접 보셔야 합니다. 물론 각 회차마다 변화하는 모습을 캡쳐한 이미지들을 모아서 &lt;b&gt;동영상 파일을 제작&lt;/b&gt;하는 것도 가능합니다. 참고로 IDL에서 동영상 파일을 만드는 방법에 관해서는 예전에 올렸던 관련 게시물들(&lt;a href=&quot;https://swrush.tistory.com/764&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크 1&lt;/a&gt;, &lt;a href=&quot;https://swrush.tistory.com/766&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크 2&lt;/a&gt;)의 내용을 참조하시면 됩니다. 이 내용을 바탕으로 동영상 파일을 만들기 위하여 바로 위의 반복형 구문의 내용을 다음과 같이 수정해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;vfile = 'image_zoom.mp4' &lt;br /&gt;fps = 60 &lt;br /&gt;oVid = IDLffVideoWrite(vfile) &lt;br /&gt;vidStream = oVid.AddVideoStream(sx, sy, fps) &lt;br /&gt;FOR j = 0, 720 DO BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;box.SetData,&amp;nbsp;[bpx,&amp;nbsp;bpx+bszx,&amp;nbsp;bpx+bszx,&amp;nbsp;bpx]+j,&amp;nbsp;[bpy,&amp;nbsp;bpy,&amp;nbsp;bpy+bszy,&amp;nbsp;bpy+bszy] &lt;br /&gt;&amp;nbsp;&amp;nbsp;i1.SetData,&amp;nbsp;data[bpx+j:bpx+bszx+j,&amp;nbsp;bpy:bpy+bszy] &lt;br /&gt;&amp;nbsp; cap = win.CopyWindow(WIDTH=sx) &lt;br /&gt;&amp;nbsp; time = oVid.Put(vidStream, cap) &lt;br /&gt;ENDFOR &lt;br /&gt;oVid.CleanUp&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 IDLffVideoWrite 클래스를 사용하는 방식으로 처리하였습니다. 이와 같은 내용으로 변경하고 전체 과정을 다시 실행하면 image_zoom.mp4라는 동영상 파일을 얻을 수 있습니다. 다만 여기서는 반복의 회차가 720까지 가도록 하였고, 변수 fps를 60으로 정의함으로써 생성되는 동영상이 1초당 60프레임으로 돌아가도록 해보았습니다. 이와 같이 생성된 동영상은 아래 링크를 통하여 보실 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/-2n-fG3TtjU&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://youtu.be/-2n-fG3TtjU&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 제시된 예제에서는 단색광 이미지 즉 배열 구조가 2차원인 이미지 데이터를 대상으로 하였는데, RGB 이미지에 대해서도 동일한 방법론을 적용할 수 있습니다. 다만 &lt;b&gt;RGB 이미지의 경우는 배열 구조가 3차원이라는 것을 감안하여 배열 인덱싱을 해야한다&lt;/b&gt;는 것만 유의하면 됩니다. 이러한 예제를 보기 위하여 이번에는 다음과 같이 새로운 이미지 파일을 대상으로 해봅시다. 즉 앞서 제시된 전체 과정에서 맨 처음 이미지 데이터를 가져오는 부분을 다음 내용을 대체합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;file&amp;nbsp;=&amp;nbsp;FILEPATH('ohare.jpg',&amp;nbsp;subdir=['examples',&amp;nbsp;'data']) &lt;br /&gt;READ_JPEG,&amp;nbsp;file,&amp;nbsp;data &lt;br /&gt;HELP,&amp;nbsp;data&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 역시 IDL의 설치 폴더에서 제공되는 ohare.jpg라는 파일을 읽게 되는데, 이 이미지는 5000x5000의 크기를 갖는 RGB 이미지입니다. 그래서 위와 같이 읽으면 얻게 되는 data는 3x5000x5000의 구조를 갖는 바이트형 배열이 됩니다. 이제 이후의 과정은 앞서 제시되었던 내용과 거의 동일합니다. 다만 배열 구조가 3차원이 되었기 때문에 인덱싱하는 부분들만 그에 맞게 변경해줘야 합니다. 일단 그래픽 창을 띄우고 표출하는 과정은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sx&amp;nbsp;=&amp;nbsp;1000 &lt;br /&gt;sy&amp;nbsp;=&amp;nbsp;500 &lt;br /&gt;win&amp;nbsp;=&amp;nbsp;WINDOW(DIMENSIONS=[sx,&amp;nbsp;sy],&amp;nbsp;/NO_TOOLBAR) &lt;br /&gt;i0&amp;nbsp;=&amp;nbsp;IMAGE(data,&amp;nbsp;MARGIN=0.02,&amp;nbsp;/CURRENT,&amp;nbsp;LAYOUT=[2,&amp;nbsp;1,&amp;nbsp;1]) &lt;br /&gt;bszx&amp;nbsp;=&amp;nbsp;400 &lt;br /&gt;bszy&amp;nbsp;=&amp;nbsp;400 &lt;br /&gt;bpx&amp;nbsp;=&amp;nbsp;3200 &lt;br /&gt;bpy&amp;nbsp;=&amp;nbsp;4100 &lt;br /&gt;box&amp;nbsp;=&amp;nbsp;POLYGON([bpx,&amp;nbsp;bpx+bszx,&amp;nbsp;bpx+bszx,&amp;nbsp;bpx],&amp;nbsp;[bpy,&amp;nbsp;bpy,&amp;nbsp;bpy+bszy,&amp;nbsp;bpy+bszy],&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;FILL_BACKGROUND=0,&amp;nbsp;COLOR='yellow',&amp;nbsp;THICK=2,&amp;nbsp;/DATA) &lt;br /&gt;img&amp;nbsp;=&amp;nbsp;&lt;b&gt;data[*,&amp;nbsp;bpx:bpx+bszx,&amp;nbsp;bpy:bpy+bszy]&lt;/b&gt; &lt;br /&gt;i1&amp;nbsp;=&amp;nbsp;IMAGE(img,&amp;nbsp;INTERPOLATE=1,&amp;nbsp;MARGIN=0.02,&amp;nbsp;/CURRENT,&amp;nbsp;LAYOUT=[2,&amp;nbsp;1,&amp;nbsp;2])&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 원본 이미지 배열인 data로부터 부분 영역에 해당되는 이미지 배열 img를 추출하는데 있어서 3차원 배열이라는 특성에 맞게 인덱싱된 것을 유의하면 됩니다. 일단 여기까지의 과정에 의하여 표출된 모습은 다음 그림과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260219_image_zoom_2.png&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDBkTf/dJMcahjcFz8/AsOKMpcqPYUovkBwpfKGgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDBkTf/dJMcahjcFz8/AsOKMpcqPYUovkBwpfKGgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDBkTf/dJMcahjcFz8/AsOKMpcqPYUovkBwpfKGgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDBkTf%2FdJMcahjcFz8%2FAsOKMpcqPYUovkBwpfKGgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1000&quot; height=&quot;500&quot; data-filename=&quot;20260219_image_zoom_2.png&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 바로 뒤에 이어지는 반복형 구문에 의한 변화 및 동영상 캡쳐의 과정에서도 이러한 부분만 유의하여 변경해주면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;vfile = 'image_zoom.mp4' &lt;br /&gt;fps = 60 &lt;br /&gt;oVid = IDLffVideoWrite(vfile) &lt;br /&gt;vidStream = oVid.AddVideoStream(sx, sy, fps) &lt;br /&gt;FOR j = 0, 1080 DO BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;box.SetData,&amp;nbsp;[bpx,&amp;nbsp;bpx+bszx,&amp;nbsp;bpx+bszx,&amp;nbsp;bpx]+j,&amp;nbsp;[bpy,&amp;nbsp;bpy,&amp;nbsp;bpy+bszy,&amp;nbsp;bpy+bszy] &lt;br /&gt;&amp;nbsp;&amp;nbsp;i1.SetData,&amp;nbsp;&lt;b&gt;data[*,&amp;nbsp;bpx+j:bpx+bszx+j,&amp;nbsp;bpy:bpy+bszy]&lt;/b&gt; &lt;br /&gt;&amp;nbsp; cap = win.CopyWindow(WIDTH=sx) &lt;br /&gt;&amp;nbsp; time = oVid.Put(vidStream, cap) &lt;br /&gt;ENDFOR &lt;br /&gt;oVid.CleanUp&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 전체 과정을 실행하면 앞선 예제에서와 마찬가지로 mp4 형식의 동영상 파일을 얻게 됩니다. 다만 여기서는 반복의 회차가 1080까지 가도록 하였고, 변수 fps를 60으로 정의함으로써 생성되는 동영상이 1초당 60프레임으로 돌아가도록 해보았습니다. 이와 같이 생성된 동영상은 아래 링크를 통하여 보실 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/zIjNkZb8ahM&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://youtu.be/zIjNkZb8ahM&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;* 이 글이 도움이 되었다면 게시물에 대하여 공감 버튼(하트 모양) 클릭 및 블로그 구독도 해주시면 더 큰 힘이 됩니다. 감사합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IDL/Image Processing</category>
      <author>이상우_IDL</author>
      <guid isPermaLink="true">https://swrush.tistory.com/829</guid>
      <comments>https://swrush.tistory.com/829#entry829comment</comments>
      <pubDate>Thu, 19 Mar 2026 15:02:39 +0900</pubDate>
    </item>
    <item>
      <title>궤적 상의 입자 운동 구현 및 애니메이션</title>
      <link>https://swrush.tistory.com/831</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;2차원 공간에 존재하는 궤적이 있고 그 위에서 움직이는 입자가 있는 상황&lt;/b&gt;&lt;/span&gt;을 가정하여 이를 &lt;b&gt;그래픽적으로 도식화하고 그 움직임을 담은 애니메이션 파일을 만들어보는 예제&lt;/b&gt;를 소개하고자 합니다. 먼저 궤적을 구성하는 점들의 좌표 데이터를 생성하는 작업부터 진행합니다. 그 과정은 다음과 같이 정의해봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n&amp;nbsp;=&amp;nbsp;400 &lt;br /&gt;t&amp;nbsp;=&amp;nbsp;[0:2*!pi:2*!pi/n] &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;0.5+COS(t) &lt;br /&gt;x&amp;nbsp;=&amp;nbsp;r*COS(t) &lt;br /&gt;y&amp;nbsp;=&amp;nbsp;r*SIN(t) &lt;br /&gt;HELP,&amp;nbsp;x,&amp;nbsp;y&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 총 401개의 X축 및 Y축 좌표값들로 구성된 배열 x 및 y를 정의하였습니다. 이러한 점들로 구성된 궤적을 그림으로 표출하기 위하여 다음과 같은 과정을 추가로 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sx&amp;nbsp;=&amp;nbsp;600 &lt;br /&gt;sy&amp;nbsp;=&amp;nbsp;600 &lt;br /&gt;win&amp;nbsp;=&amp;nbsp;WINDOW(DIMENSIONS=[sx,&amp;nbsp;sy],&amp;nbsp;/NO_TOOLBAR) &lt;br /&gt;p = PLOT(x, y, XRANGE=[-0.3, 1.7], COLOR='green', $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; FONT_SIZE=11, MARGIN=0.1, /CURRENT) &lt;br /&gt;sym = SYMBOL(x[0], y[0], 'circle', /SYM_FILLED, SYM_SIZE=2, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; SYM_COLOR='red', /DATA)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 그래픽 창을 띄운 다음 &lt;b&gt;PLOT 함수&lt;/b&gt;를 사용하여 이 궤적을 표시하고 &lt;b&gt;SYMBOL 함수&lt;/b&gt;를 사용하여 첫번째 점의 위치에 원형 심볼을 추가하였습니다. 표출된 그림을 보면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260311_motion_on_curve.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n3SSL/dJMcabKcSyN/k98Lr1Lr69ZVZj0kmNowa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n3SSL/dJMcabKcSyN/k98Lr1Lr69ZVZj0kmNowa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n3SSL/dJMcabKcSyN/k98Lr1Lr69ZVZj0kmNowa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn3SSL%2FdJMcabKcSyN%2Fk98Lr1Lr69ZVZj0kmNowa1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260311_motion_on_curve.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;원형 심볼의 위치를 순차적으로 변화시켜서 궤적상에서 운동하는 모습을 구현&lt;/b&gt;&lt;/span&gt;해봅시다. 이러한 작업을 위해서는 반복형 구문을 사용하면서 그 안에서 심볼의 위치를 순차적으로 변경하면 되는데, 구체적으로는 &lt;b&gt;SYMBOL 함수로 구현되어 있는 심볼 개체에 대하여 SetData 메서드를 사용하여 위치를 변경&lt;/b&gt;해주면 됩니다. 이러한 작업을 위하여 추가되어야 할 내용은 다음과 같이 매우 간단합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FOR j = 0, n DO sym.SetData, x[j], y[j]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같은 내용까지 실행하면 그래픽 창에 표출된 그림 내에서 심볼이 궤적을 따라 순차적으로 이동하는 모습을 볼 수 있을 것입니다. 다만 이왕이면 이렇게 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;움직이는 모습을 애니메이션으로 담은 파일을 제작&lt;/b&gt;&lt;/span&gt;할 수 있다면 더 좋을 것입니다. 그러면 &lt;b&gt;애니메이션 GIF 파일&lt;/b&gt;로 만들어보기로 합시다. 이를 위해서는 방금전에 제시되었던 반복형 구문의 내용이 대폭 수정되어야 합니다. 반복 회차마다 표출되는 화면을 캡쳐하여 프레임별 이미지로 삽입하는 과정이 추가되어야 하기 때문입니다. 애니메이션 GIF 파일을 만드는 방법에 관해서는 예전에 &lt;a href=&quot;https://swrush.tistory.com/767&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;관련 게시물&lt;/a&gt;을 통하여 소개한 바 있습니다. 따라서 그 방법에 관한 자세한 내용은 이 게시물을 참조하기로 하고, 이 내용을 바탕으로 하여 다음과 같이 처리해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wfile = 'motion_on_curve.gif' &lt;br /&gt;FOR j = 0, n DO BEGIN &lt;br /&gt;&amp;nbsp; sym.SetData, x[j], y[j] &lt;br /&gt;&amp;nbsp; cap = win.CopyWindow(WIDTH=sx) &lt;br /&gt;&amp;nbsp; frame = COLOR_QUAN(cap, 1, r, g, b) &lt;br /&gt;&amp;nbsp; WRITE_GIF, wfile, frame, r, g, b, /MULTIPLE, $ &lt;br /&gt;&amp;nbsp; &amp;nbsp; DELAY_TIME=2, REPEAT_COUNT=0 &lt;br /&gt;ENDFOR &lt;br /&gt;WRITE_GIF, wfile, /CLOSE&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 매 회차마다 SetData 메서드에 의하여 변화된 그림의 모습을 &lt;b&gt;CopyWindow 메서드&lt;/b&gt;를 사용하여 캡쳐하고, 이렇게 캡쳐된 이미지를 &lt;b&gt;COLOR_QUAN 함수&lt;/b&gt;를 사용하여 8비트 이미지로 변환한 다음 이를 &lt;b&gt;WRITE_GIF 명령&lt;/b&gt;에 투입하는 방식으로 작업이 진행됩니다. 또한 DELAY_TIME 키워드를 2로 설정하여 초당 50 프레임으로 애니메이션이 진행되도록 하였고 REPEAT_COUNT 키워드를 0으로 설정하여 무한반복이 되도록 하였습니다. 이 작업이 모두 끝나면 motion_on_curve.gif라는 이름의 애니메이션 GIF 파일이 생성될 것입니다. 이 파일은 아래에 첨부하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260311_motion_on_curve.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/25UeE/dJMcabKcSza/nDJaecUs7GJ6LQKIkROWk1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/25UeE/dJMcabKcSza/nDJaecUs7GJ6LQKIkROWk1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/25UeE/dJMcabKcSza/nDJaecUs7GJ6LQKIkROWk1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/25UeE/dJMcabKcSza/nDJaecUs7GJ6LQKIkROWk1/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260311_motion_on_curve.gif&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 궤적 상에서 심볼이 움직이는 애니메이션이 진행되는 모습을 바로 확인할 수 있습니다. 그리고 이러한 애니메이션을 GIF 대신 &lt;b&gt;MP4 형식의 동영상 파일로 제작&lt;/b&gt;하는 것도 가능합니다. 그 방법에 관해서도 관련 게시물들(&lt;a href=&quot;https://swrush.tistory.com/764&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크 1&lt;/a&gt;, &lt;a href=&quot;https://swrush.tistory.com/766&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크 2&lt;/a&gt;)을 예전에 올린 바 있습니다. 따라서 이 내용을 바탕으로 하여 MP4 동영상 파일로 만드는 과정을 작성해본다면 대략 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nn&amp;nbsp;=&amp;nbsp;n*2 &lt;br /&gt;data_cap&amp;nbsp;=&amp;nbsp;BYTARR(3,&amp;nbsp;sx,&amp;nbsp;sy,&amp;nbsp;nn) &lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;nn-1&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;jj&amp;nbsp;=&amp;nbsp;j&amp;nbsp;MOD&amp;nbsp;400 &lt;br /&gt;&amp;nbsp;&amp;nbsp;sym.SetData,&amp;nbsp;x[jj],&amp;nbsp;y[jj] &lt;br /&gt;&amp;nbsp;&amp;nbsp;cap = win.CopyWindow(WIDTH=sx) &lt;br /&gt;&amp;nbsp; data_cap[*, *, *, j] = cap &lt;br /&gt;ENDFOR &lt;br /&gt;WRITE_VIDEO, 'motion_on_curve.mp4', data_cap, VIDEO_FPS=60&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 기본적으로 &lt;b&gt;WRITE_VIDEO 명령&lt;/b&gt;을 사용하는 방식으로 처리하였습니다. 다만 애니메이션 GIF와는 달리 여기서는 무한반복이 되도록 할 수는 없기 때문에 2회만 반복되도록 하였습니다. 이를 위하여 nn을 위와 같이 정의하였고 반복형 구문 내에서 x 및 y를 인덱싱할 목적으로 400을 넘지 않는 인덱스 jj를 정의한 점 등을 유의하면 됩니다. 이와 같은 방식으로 생성된 동영상은 아래 링크를 통하여 보실 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtube.com/shorts/QSu9XhuWpBs?feature=share&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtube.com/shorts/QSu9XhuWpBs?feature=share&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;* 이 글이 도움이 되었다면 게시물에 대하여 공감 버튼(하트 모양) 클릭 및 블로그 구독도 해주시면 더 큰 힘이 됩니다. 감사합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IDL/New Graphics</category>
      <author>이상우_IDL</author>
      <guid isPermaLink="true">https://swrush.tistory.com/831</guid>
      <comments>https://swrush.tistory.com/831#entry831comment</comments>
      <pubDate>Fri, 13 Mar 2026 15:04:06 +0900</pubDate>
    </item>
    <item>
      <title>데이터 포인트들을 다양한 색상으로 표출하기 [3]</title>
      <link>https://swrush.tistory.com/830</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;2차원 공간상에 흩어져있는 다수의 데이터 포인트들 다양한 색상으로 표출하는 방법&lt;/b&gt;&lt;/span&gt;에 관한 게시물들(&lt;a href=&quot;https://swrush.tistory.com/687&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크 1&lt;/a&gt;, &lt;a href=&quot;https://swrush.tistory.com/694&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;링크 2&lt;/a&gt;)을 올렸던 적이 있습니다. 그래서 이러한 방식의 구현을 위하여 &lt;b&gt;SCATTERPLOT 및 BUBBLEPLOT 함수&lt;/b&gt;를 사용하는 방법 및 예제들을 다양하게 소개한 바 있는데요. 오늘은 이러한 연장선상에 있는 또 다른 예제들을 소개해보고자 합니다. 먼저 예제 데이터를 생성하는 과정부터 시작하면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n&amp;nbsp;=&amp;nbsp;100 &lt;br /&gt;x1&amp;nbsp;=&amp;nbsp;RANDOMU(-1,&amp;nbsp;n)*100 &lt;br /&gt;y1&amp;nbsp;=&amp;nbsp;RANDOMU(-2,&amp;nbsp;n)*100 &lt;br /&gt;x2&amp;nbsp;=&amp;nbsp;RANDOMU(-3,&amp;nbsp;n)*100 &lt;br /&gt;y2&amp;nbsp;=&amp;nbsp;RANDOMU(-4,&amp;nbsp;n)*100 &lt;br /&gt;x3&amp;nbsp;=&amp;nbsp;RANDOMU(-5,&amp;nbsp;n)*100 &lt;br /&gt;y3&amp;nbsp;=&amp;nbsp;RANDOMU(-6,&amp;nbsp;n)*100&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 2차원 공간상에 분포하는 100개의 포인트들로 구성되는 3종의 데이터들 각각의 위치 좌표들인 x1, y1, x2, y2, x3, y3을 가정하였습니다. 이들 각각은 0~100의 범위를 갖는 100개의 값들로 구성됩니다. 따라서 &lt;b&gt;총 300개의 데이터 포인트들이 존재하면서 이들이 3종으로 구분되는 상황&lt;/b&gt;이라고 보면 됩니다. 그러면 첫번째 데이터인 x1, y1에 대하여 &lt;b&gt;SCATTERPLOT 함수&lt;/b&gt;를 사용하여 표출해봅시다. 이 과정은 다음과 같이 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;win&amp;nbsp;=&amp;nbsp;WINDOW(DIMENSIONS=[600,&amp;nbsp;600],&amp;nbsp;/NO_TOOLBAR) &lt;br /&gt;p1&amp;nbsp;=&amp;nbsp;SCATTERPLOT(x1,&amp;nbsp;y1,&amp;nbsp;XRANGE=[-10,&amp;nbsp;110],&amp;nbsp;YRANGE=[-10,&amp;nbsp;110],&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;XTICKLEN=1, YTICKLEN=1, XMINOR=0, YMINOR=0, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; XGRIDSTYLE=1, YGRIDSTYLE=1, $ &lt;br /&gt;&amp;nbsp;&amp;nbsp;SYMBOL='circle',&amp;nbsp;/SYM_FILLED,&amp;nbsp;SYM_SIZE=3,&amp;nbsp;SYM_COLOR='red',&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;MARGIN=0.1, FONT_SIZE=11, /CURRENT, NAME='data 1')&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 x1, y1 데이터를 붉은색 원형 심볼들로 표시하였으며, 좌표들의 위치 및 심볼들의 크기를 감안하여 X축 및 Y축의 범위에 좀 더 여유를 두었습니다. 또한 점선형의 격자선을 그려주면서 마이너 눈금들은 제거하였습니다. 일단 여기까지의 내용에 의한 표출 결과는 다음 그림과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260305_scatterplot_0a.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OqiZG/dJMcahQ5rV0/xJNQ2Jy92mHX9vvGmkD7Q0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OqiZG/dJMcahQ5rV0/xJNQ2Jy92mHX9vvGmkD7Q0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OqiZG/dJMcahQ5rV0/xJNQ2Jy92mHX9vvGmkD7Q0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOqiZG%2FdJMcahQ5rV0%2FxJNQ2Jy92mHX9vvGmkD7Q0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260305_scatterplot_0a.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 나머지 데이터들인 x2, y2, x3, y3에 해당되는 포인트들을 각각 다른 색상으로 중첩시켜봅시다. 이를 위하여 다음과 같은 내용을 추가합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p2&amp;nbsp;=&amp;nbsp;SCATTERPLOT(x2,&amp;nbsp;y2,&amp;nbsp;SYMBOL='circle',&amp;nbsp;/SYM_FILLED,&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;SYM_SIZE=3, SYM_COLOR='green', /OVERPLOT, NAME='data 2') &lt;br /&gt;p3&amp;nbsp;=&amp;nbsp;SCATTERPLOT(x3,&amp;nbsp;y3,&amp;nbsp;SYMBOL='circle',&amp;nbsp;/SYM_FILLED,&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;SYM_SIZE=3, SYM_COLOR='blue', /OVERPLOT, NAME='data 3')&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lgd&amp;nbsp;=&amp;nbsp;LEGEND(TARGET=[p1,&amp;nbsp;p2,&amp;nbsp;p3],&amp;nbsp;ORIENTATION=1,&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;HORIZONTAL_ALIGNMENT=0.5,&amp;nbsp;HORIZONTAL_SPACING=0.06,&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;VERTICAL_ALIGNMENT=0.5, VERTICAL_SPACING=0.07, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; SAMPLE_WIDTH=0, LINESTYLE=0, POSITION=[0.5, 0.95], /NORMAL)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 두번째 데이터가 초록색 그리고 세번째 데이터가 파란색 심볼들로 표시되도록 하였습니다. 그리고 이제는 3종의 데이터들이 혼재된 상황이기 때문에 &lt;b&gt;LEGEND 함수를 사용하여 범례를 상단에 추가&lt;/b&gt;하였습니다. 여기서 LEGEND 함수가 사용된 내용이 약간 복잡한데, ORIENTATION 속성을 1로 설정하여 수평 방향이 되도록 하였고 데이터 포인트 심볼이 하나씩만 표시되도록 하기 위하여 SAMPLE_WIDTH 속성을 0으로 설정하였습니다. 그리고 여백 및 위치에 대한 세부 조정을 위하여 수평 및 수직 방향에 대한 _ALIGNMENT 및 _SPACING 속성들의 값을 적절히 설정하였습니다. 여기까지의 내용을 실행한 결과는 다음 그림과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260305_scatterplot_0b.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzXUKH/dJMcajagkGr/16z90jXKz1KWPIGoK0MjfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzXUKH/dJMcajagkGr/16z90jXKz1KWPIGoK0MjfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzXUKH/dJMcajagkGr/16z90jXKz1KWPIGoK0MjfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzXUKH%2FdJMcajagkGr%2F16z90jXKz1KWPIGoK0MjfK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260305_scatterplot_0b.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 그림 자체는 나쁘지 않은데 &lt;b&gt;나중에 중첩된 데이터 심볼들이 기존에 표시된 심볼들을 덮어쓰는 현상&lt;/b&gt;이 좀 거슬립니다. 그래서 이러한 문제에 대한 해결책으로서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;심볼들을 반투명으로 처리&lt;/b&gt;&lt;/span&gt;해보면 어떨까 합니다. 이러한 처리를 위해서는 SCATTERPLOT 함수들 각각에 대하여 &lt;b&gt;TRANSPARENCY 속성&lt;/b&gt;을 추가적으로 사용하면 됩니다. 즉 위의 내용에서 SCATTERPLOT 함수가 사용된 부분들만 다음과 같이 변경하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p1&amp;nbsp;=&amp;nbsp;SCATTERPLOT(x1,&amp;nbsp;y1,&amp;nbsp;XRANGE=[-10,&amp;nbsp;110],&amp;nbsp;YRANGE=[-10,&amp;nbsp;110],&amp;nbsp;$&lt;br /&gt;&amp;nbsp;&amp;nbsp;XTICKLEN=1, YTICKLEN=1, XMINOR=0, YMINOR=0, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; XGRIDSTYLE=1, YGRIDSTYLE=1, $&lt;br /&gt;&amp;nbsp;&amp;nbsp;SYMBOL='circle',&amp;nbsp;/SYM_FILLED,&amp;nbsp;SYM_SIZE=3,&amp;nbsp;SYM_COLOR='red',&amp;nbsp;$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &lt;b&gt;TRANSPARENCY=50&lt;/b&gt;, MARGIN=0.1, FONT_SIZE=11, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; /CURRENT, NAME=' data 1')&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p2&amp;nbsp;=&amp;nbsp;SCATTERPLOT(x2,&amp;nbsp;y2,&amp;nbsp;SYMBOL='circle',&amp;nbsp;/SYM_FILLED,&amp;nbsp;$&lt;br /&gt;&amp;nbsp;&amp;nbsp;SYM_SIZE=3,&amp;nbsp;SYM_COLOR='green', &lt;b&gt;TRANSPARENCY=50&lt;/b&gt;, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; /OVERPLOT, NAME=' data 2')&lt;br /&gt;p3&amp;nbsp;=&amp;nbsp;SCATTERPLOT(x3,&amp;nbsp;y3,&amp;nbsp;SYMBOL='circle',&amp;nbsp;/SYM_FILLED,&amp;nbsp;$&lt;br /&gt;&amp;nbsp;&amp;nbsp;SYM_SIZE=3,&amp;nbsp;SYM_COLOR='blue', &lt;b&gt;TRANSPARENCY=50&lt;/b&gt;, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; /OVERPLOT, NAME=' data 3')&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 표시되는 모든 심볼들에 대하여 투명도가 50%가 되도록 설정한 것입니다. 이러한 변경사항을 반영하여 다시 실행해보면 그 결과는 다음 그림과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260305_scatterplot_1.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s8uTE/dJMcacoInW2/pzoe53Y9UkKOVQZ1KPcfq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s8uTE/dJMcacoInW2/pzoe53Y9UkKOVQZ1KPcfq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s8uTE/dJMcacoInW2/pzoe53Y9UkKOVQZ1KPcfq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs8uTE%2FdJMcacoInW2%2Fpzoe53Y9UkKOVQZ1KPcfq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260305_scatterplot_1.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 그림을 보면 투명도를 적용한 덕분에 심볼들이 가려져서 완전히 보이지 않는 문제가 어느 정도 해결된 것으로 보입니다. 일단 여기서는 SCATTERPLOT 함수를 사용하면서 TRANSPARENCY 속성을 추가적으로 설정해보았는데요. 사실 이와 같은 표출은 BUBBLEPLOT 함수로도 구현이 가능합니다. 만약 위와 같은 표출을 &lt;b&gt;SCATTERPLOT 함수 대신 BUBBLEPLOT 함수로 구현&lt;/b&gt;한다면 그 과정은 대략 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;win&amp;nbsp;=&amp;nbsp;WINDOW(DIMENSIONS=[600,&amp;nbsp;600],&amp;nbsp;/NO_TOOLBAR) &lt;br /&gt;p1&amp;nbsp;=&amp;nbsp;&lt;b&gt;BUBBLEPLOT&lt;/b&gt;(x1,&amp;nbsp;y1,&amp;nbsp;XRANGE=[-10,&amp;nbsp;110],&amp;nbsp;YRANGE=[-10,&amp;nbsp;110],&amp;nbsp;$ &lt;br /&gt;&amp;nbsp;&amp;nbsp;XTICKLEN=1, YTICKLEN=1, XMINOR=0, YMINOR=0, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; XGRIDSTYLE=1, YGRIDSTYLE=1, $ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;COLOR='red', SIZING=0.4, BORDER=0&lt;/b&gt;, TRANSPARENCY=50, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;MARGIN=0.1, FONT_SIZE=11, /CURRENT, NAME='data 1') &lt;br /&gt;p2 = &lt;b&gt;BUBBLEPLOT&lt;/b&gt;(x2, y2, &lt;b&gt;COLOR='green', SIZING=0.4, BORDER=0&lt;/b&gt;, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; TRANSPARENCY=50, /OVERPLOT, NAME='data 2') &lt;br /&gt;p3 = &lt;b&gt;BUBBLEPLOT&lt;/b&gt;(x3, y3, &lt;b&gt;COLOR='blue', SIZING=0.4, BORDER=0&lt;/b&gt;, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; TRANSPARENCY=50, /OVERPLOT, NAME='data 3') &lt;br /&gt;lgd = LEGEND(TARGET=[p1, p2, p3], ORIENTATION=1, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; HORIZONTAL_ALIGNMENT=0.5, VERTICAL_ALIGNMENT=0.5, $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; VERTICAL_SPACING=0.05, SAMPLE_WIDTH=0, $ &lt;br /&gt;&amp;nbsp;&amp;nbsp;LINESTYLE=0,&amp;nbsp;POSITION=[0.5,&amp;nbsp;0.95],&amp;nbsp;/NORMAL)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 BUBBLEPLOT 함수의 특성에 맞춰서 &lt;b&gt;COLOR 및 SIZING 속성&lt;/b&gt;을 사용하여 색상 및 크기를 설정하고 &lt;b&gt;BORDER 속성&lt;/b&gt;을 0으로 설정하여 경계선은 표시되지 않도록 하였습니다. 그 외 나머지 내용은 거의 유사합니다. 이 내용을 실행하면 그 결과는 다음 그림과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260305_scatterplot_4.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cChZbU/dJMcaiCrvqW/EhAsU4hx4h8ke5eFK8iNBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cChZbU/dJMcaiCrvqW/EhAsU4hx4h8ke5eFK8iNBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cChZbU/dJMcaiCrvqW/EhAsU4hx4h8ke5eFK8iNBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcChZbU%2FdJMcaiCrvqW%2FEhAsU4hx4h8ke5eFK8iNBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260305_scatterplot_4.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 그림을 보면 앞서 SCATTERPLOT 함수를 사용했던 결과와 거의 유사한 것으로 보입니다. 따라서 이러한 유형의 표출을 위해서는 SCATTERPLOT 또는 BUBBLEPLOT 함수 중 어느 것을 사용해도 무방하다고 봐도 될 것 같습니다. 다만 여기서 한가지 주목할 부분은 바로 LEGEND 함수로 구현된 범례입니다. 지금 &lt;b&gt;BUBBLEPLOT 함수로 구현된 그림에서는 범례에 표시된 심볼들에 대해서도 투명도가 적용된다&lt;/b&gt;는 것을 확인할 수 있습니다. 반면 앞서 SCATTERPLOT 함수로 구현했던 그림을 보면 범례의 심볼들에는 투명도가 전혀 반영되어 있지 않습니다. 따라서 방금 실행했던 내용에서는 투명도의 수치가 플롯의 심볼들 뿐 아니라 범례의 심볼들에 대해서도 동일하게 적용된다고 보면 됩니다. 만약 위의 내용에서 투명도 수치인 TRANSPARENCY 속성의 값을 30으로 변경해본다면 그 결과는 다음 그림과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260305_scatterplot_4b.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vTHum/dJMcag5Jm8Y/DamcK4Nx0kG5DKByKbgekK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vTHum/dJMcag5Jm8Y/DamcK4Nx0kG5DKByKbgekK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vTHum/dJMcag5Jm8Y/DamcK4Nx0kG5DKByKbgekK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvTHum%2FdJMcag5Jm8Y%2FDamcK4Nx0kG5DKByKbgekK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260305_scatterplot_4b.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 투명도의 수치를 낮추었으므로 약간 더 불투명하게 보이게 됩니다. 그러면 이번에는 반대로 투명도의 수치를 70으로 높인다면 더 투명하게 보일텐데 실제로 그 결과를 보면 다음 그림과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20260305_scatterplot_4c.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1C6WQ/dJMcaih9Ncu/b4Rg64IBd2MWTfvnfCIUaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1C6WQ/dJMcaih9Ncu/b4Rg64IBd2MWTfvnfCIUaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1C6WQ/dJMcaih9Ncu/b4Rg64IBd2MWTfvnfCIUaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1C6WQ%2FdJMcaih9Ncu%2Fb4Rg64IBd2MWTfvnfCIUaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;600&quot; data-filename=&quot;20260305_scatterplot_4c.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 플롯 자체의 심볼들 뿐 아니라 범례의 심볼들까지도 투명도가 반영되도록 하고 싶을 경우에는 BUBBLEPLOT 함수를 사용하면 되고, 굳이 그럴 필요까지는 없을 경우라면 SCATTERPLOT 함수를 사용해도 무방하다고 보면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;* 이 글이 도움이 되었다면 게시물에 대하여 공감 버튼(하트 모양) 클릭 및 블로그 구독도 해주시면 더 큰 힘이 됩니다. 감사합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IDL/New Graphics</category>
      <author>이상우_IDL</author>
      <guid isPermaLink="true">https://swrush.tistory.com/830</guid>
      <comments>https://swrush.tistory.com/830#entry830comment</comments>
      <pubDate>Fri, 6 Mar 2026 15:40:46 +0900</pubDate>
    </item>
    <item>
      <title>배열간 연산과 반복형 구문에 의한 연산 사이의 비교 [2]</title>
      <link>https://swrush.tistory.com/828</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://swrush.tistory.com/827&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;지난 회차 게시물&lt;/a&gt;에서는 배열들을 사용하여 연산 결과를 얻는 방식에 있어서 &lt;b&gt;배열간 연산과 반복형 구문에 의한 연산&lt;/b&gt;이라는 두가지 방식에 대하여 살펴보고 서로 비교해보았습니다. 특히 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;대용량 데이터를 다루게 될 경우에는 두 방식의 소요 시간이 서로 상당히 큰 차이를 보인다&lt;/b&gt;&lt;/span&gt;는 것도 함께 확인한 바 있습니다. 그러면 이번 회차에는 이러한 차이를 가늠할 수 있는 다른 예제를 살펴보기로 하겠습니다. 이번 예제에서는 &lt;b&gt;반복형 구문 내에서 IF와 같은 조건형 구문이 사용되는 경우&lt;/b&gt;입니다. 예제를 보면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n&amp;nbsp;=&amp;nbsp;10000000 &lt;br /&gt;a&amp;nbsp;=&amp;nbsp;RANDOMU(-1,&amp;nbsp;n)*100 &lt;br /&gt;b&amp;nbsp;=&amp;nbsp;RANDOMU(-2,&amp;nbsp;n)*100 &lt;br /&gt;c&amp;nbsp;=&amp;nbsp;RANDOMU(-3,&amp;nbsp;n)*100&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TIC &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;FLTARR(n) &lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;n-1&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;IF&amp;nbsp;a[j]&amp;nbsp;GE&amp;nbsp;50&amp;nbsp;THEN&amp;nbsp;r[j]&amp;nbsp;=&amp;nbsp;(a[j]-40)/SQRT(b[j]+c[j]) &lt;br /&gt;&amp;nbsp;&amp;nbsp;IF&amp;nbsp;a[j]&amp;nbsp;LT&amp;nbsp;50&amp;nbsp;THEN&amp;nbsp;r[j]&amp;nbsp;=&amp;nbsp;(a[j]+10)/SQRT(b[j]+c[j]) &lt;br /&gt;ENDFOR &lt;br /&gt;TOC&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 예제에서는 반복형 구문 내에서 IF문을 사용하여 특정한 조건에 따라 서로 다른 유형의 연산이 수행되도록 하였습니다. 실제로 이와 같은 방식으로 작업을 하게 되는 경우들이 종종 있습니다. 결론부터 얘기하면 이러한 방식으로 처리하면 시간은 많이 걸립니다. 즉 반복형 구문이라는 것만으로도 어느 정도 시간이 걸리게 되는데, 거기다가 그 안에서 조건형 구문까지 처리해야 한다면 이로 인한 시간이 더해지게 됩니다. 제 PC의 IDL에서 위의 내용을 실행해본 결과는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;1.9200001&amp;nbsp;seconds.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 약 1.92초 정도의 시간이 걸리는 것으로 측정되었습니다. 물론 이러한 수치는 실행할 때마다 다를 수 있고 여러분의 PC에서도 다르게 나올 수 있습니다. 하지만 그리 적은 시간은 아닙니다. 그리고 여기서는 연산의 결과값들을 담은 배열 r을 얻었는데, 확인을 위하여 이 배열의 처음 10개의 값들만 출력해보면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;9&amp;nbsp;DO&amp;nbsp;PRINT,&amp;nbsp;r[j]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.92828 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2.56979 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4.68861 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.63488 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3.24914 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0.964956 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3.58475 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3.35747 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.19523 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;3.71283 &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 이러한 &lt;b&gt;반복형 구문에 의한 연산보다 배열간 연산이 더 빠르다&lt;/b&gt;는 것은 이미 지난 회차 게시물에서 확인한 바 있습니다. 다만 위와 같이 배열 내의 값에 따라서 조건부로 서로 다른 연산을 수행해야 하는 경우라면 작업자의 입장에서는 배열간 연산의 방식으로 처리하기가 어렵지않을까 하는 생각이 들 수도 있고, 그러한 이유로 그냥 저렇게 반복형 구문으로 처리를 하게 되는 경우도 꽤 있을 것입니다. 물론 그렇게 해도 큰 문제는 없습니다. 시간이 어느 정도 더 걸릴 수도 있지만 그 차이가 아주 크지만 않다면 그냥 위와 같이 처리해도 무방합니다. 하지만 데이터의 양이 많고 처리할 연산 작업도 더 복잡한 경우라면 얘기가 달라질 수 있습니다. 이런 경우에는 작업의 효율과 소요 시간에 대한 고려를 해야합니다. 따라서 위와 같은 작업을 배열간 연산으로 처리할 수 있다면 더 좋을 것 같은데요. 위와 같이 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;배열 내 값에 따라 조건부로 연산의 내용이 달라지는 작업을 배열간 연산으로 처리하는 것도 가능&lt;/b&gt;&lt;/span&gt;합니다. 즉 위의 내용을 배열간 연산의 방식으로 변경한다면 그 내용은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TIC &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;FLTARR(n) &lt;br /&gt;w1&amp;nbsp;=&amp;nbsp;WHERE(a&amp;nbsp;GE&amp;nbsp;50) &lt;br /&gt;r[w1]&amp;nbsp;=&amp;nbsp;(a[w1]-40)/SQRT(b[w1]+c[w1]) &lt;br /&gt;w2&amp;nbsp;=&amp;nbsp;WHERE(a&amp;nbsp;LT&amp;nbsp;50) &lt;br /&gt;r[w2]&amp;nbsp;=&amp;nbsp;(a[w2]+10)/SQRT(b[w2]+c[w2]) &lt;br /&gt;TOC&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 가장 주목할 부분은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;WHERE 함수를 사용&lt;/b&gt;&lt;/span&gt;한 것입니다. 즉 앞서 반복형 구문에 의한 작업에서는 IF 구문을 사용하여 배열 a의 값에 따라 연산 과정이 다르게 적용된 바 있는데, 여기서는 배열 a의 값에 대한 &lt;b&gt;판단을 WHERE 함수로 미리 해두고 그러한 조건에 맞는 경우들에 대해서만 배열간 연산으로 처리&lt;/b&gt;한 것입니다. 실제로 이와 같은 형태로 처리 방식을 변경해도 결과는 동일하게 나옵니다. 앞서 해봤던 것처럼 배열 r의 값들을 출력해보면 확인할 수 있습니다. 그리고 실행에 걸린 시간을 보면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.088999987&amp;nbsp;seconds.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 약 0.089초 정도가 걸리는 것으로 나옵니다. 앞서 &lt;b&gt;반복형 구문에 의한 연산보다 훨씬 빠르다&lt;/b&gt;는 것을 알 수 있습니다. 배수로는 약 21배 정도입니다. 물론 배열의 크기, 연산의 복잡성 등에 따라서는 이러한 차이가 더 크게 나타날 수도 있습니다. 어쨌든 이러한 결과를 본다면, 우리가 &lt;b&gt;대용량 배열 데이터를 처리하는 작업을 해야 할 경우에는 가급적이면 반복형 구문에 의한 연산보다는 배열간 연산으로 처리하는 방향으로 코딩을 하는 것이 더 효율적&lt;/b&gt;이라는 것을 알 수 있습니다. 물론 작업의 특성에 따라서는 이게 어려운 경우도 있습니다. 그러한 예제를 보면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TIC &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;FLTARR(n) &lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;n-1&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;tmp&amp;nbsp;=&amp;nbsp;a[j]/SQRT(b[j]+c[j])+RANDOMU(seed)*10 &lt;br /&gt;&amp;nbsp;&amp;nbsp;IF&amp;nbsp;tmp&amp;nbsp;LT&amp;nbsp;50&amp;nbsp;THEN&amp;nbsp;r[j]&amp;nbsp;=&amp;nbsp;a[j]/SQRT(b[j]+c[j])+5&amp;nbsp;ELSE&amp;nbsp;r[j]&amp;nbsp;=&amp;nbsp;a[j]/SQRT(b[j]+c[j])-5 &lt;br /&gt;ENDFOR &lt;br /&gt;TOC&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 내용을 보면 반복형 구문의 내부에서 임시로 계산된 tmp의 값에 따라서 연산의 과정이 다르게 수행됩니다. 그런데 tmp의 계산 과정을 보면 RANDOMU 함수가 사용되었는데 이렇게 하면 예측할 수 없는 난수값이 생성되기 때문에 사전에 미리 배열화를 해두기가 어렵습니다. 물론 예제로 제시하기 위하여 제가 인위적으로 약간 어거지성 연산을 가정한 것이긴 합니다. 어쨌든 위의 내용을 실행해보면 예상대로 꽤 많은 시간이 걸리는 것으로 나옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;3.2830000&amp;nbsp;seconds.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 약 3.28초 정도가 나오는데 앞서 했던 연산들에 비해서는 상당히 긴 시간입니다. 따라서 배열간 연산으로 바꿀 수만 있다면 그렇게 하는 것이 좋겠지만, 실전에서는 작업의 특성에 따라서는 위와 같이 어쩔 수 없이 반복형 구문을 사용해야만 하는 경우도 분명히 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨌든 중요한 것은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;대용량의 데이터를 담은 배열들에 대한 연산을 수행하는데 있어서는 가급적이면 배열간 연산으로 처리하는 것이 좋다&lt;/b&gt;&lt;/span&gt;는 것입니다. 물론 작업의 특성에 따라 어쩔 수 없이 반복형 구문을 사용해야 하는 경우들도 있겠지만, 그런 경우들을 제외한 나머지 케이스들에 대해서는 배열간 연산으로 수행될 수 있도록 하는 것이 가장 효율적이라는 것을 염두에 두는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;* 이 글이 도움이 되었다면 게시물에 대하여 공감 버튼(하트 모양) 클릭 및 블로그 구독도 해주시면 더 큰 힘이 됩니다. 감사합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IDL/Programming</category>
      <author>이상우_IDL</author>
      <guid isPermaLink="true">https://swrush.tistory.com/828</guid>
      <comments>https://swrush.tistory.com/828#entry828comment</comments>
      <pubDate>Thu, 26 Feb 2026 15:42:08 +0900</pubDate>
    </item>
    <item>
      <title>배열간 연산과 반복형 구문에 의한 연산 사이의 비교 [1]</title>
      <link>https://swrush.tistory.com/827</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 IDL에서 대용량 데이터를 처리하는데 있어서는 배열로 정의된 데이터를 다루는 것이 일반적입니다. 즉 대용량의 데이터를 배열에 담고 이러한 배열에 대하여 필요한 연산을 수행하는 방식입니다. 이러한 작업에 있어서는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;반복형 구문을 사용하는 연산&lt;/b&gt;&lt;/span&gt;을 수행하는 경우도 있고 그냥 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;배열끼리의 연산&lt;/b&gt;&lt;/span&gt;으로 처리하는 경우도 있습니다. 통상적으로는 배열끼리의 연산으로 처리하는 경우가 많지만 작업의 특성에 따라서는 반복형 구문을 사용하는 연산을 하게 되는 경우도 있습니다. 오늘은 이러한 &lt;b&gt;두가지 연산 방식을 서로 비교해보고 그 차이점도 확인&lt;/b&gt;해보고자 합니다. 이를 위하여 간단한 예제를 다음과 같이 작성해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n = 10&lt;br /&gt;a&amp;nbsp;=&amp;nbsp;RANDOMU(-1,&amp;nbsp;n)*100 &lt;br /&gt;b&amp;nbsp;=&amp;nbsp;RANDOMU(-2,&amp;nbsp;n)*100 &lt;br /&gt;c&amp;nbsp;=&amp;nbsp;RANDOMU(-3,&amp;nbsp;n)*100&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 3종의 배열들인 a, b, c를 정의하였는데 각 배열은 0~100의 범위를 갖는 10개의 실수형 값들로 구성됩니다. 이러한 배열들에 대하여 특정한 연산을 수행하는 경우를 가정해봅시다. 예를 들면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;r&amp;nbsp;=&amp;nbsp;a/SQRT(b+c)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 배열 a, b, c를 모두 투입하여 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;배열간 연산&lt;/b&gt;&lt;/span&gt;을 수행하고 그 결과를 담은 배열 r을 얻었습니다. 이러한 방식의 배열간 연산은 우리가 흔히 하는 작업이고 별로 특별할 것은 없습니다. 결과값들을 살펴보기 위하여 다음과 같이 반복형 구문을 사용하여 출력해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;n-1&amp;nbsp;DO&amp;nbsp;PRINT,&amp;nbsp;r[j]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력된 내용을 보면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0.952586 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.35537 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;8.34884 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5.65442 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6.58985 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;4.02052 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;7.35813 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;6.98115 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0.181805 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;2.74484&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 이번에는 동일한 작업을 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;반복형 구문을 사용하는 연산&lt;/b&gt;&lt;/span&gt;으로 수행해봅시다. 즉 다음과 같은 방식으로 처리하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;r&amp;nbsp;=&amp;nbsp;FLTARR(n) &lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;n-1&amp;nbsp;DO&amp;nbsp;r[j]&amp;nbsp;=&amp;nbsp;a[j]/SQRT(b[j]+c[j])&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 결과값들을 담을 배열 r을 미리 정의한 다음, 반복형 구문을 사용하여 그 내부에서 순차적으로 연산을 수행하고 결과값을 담는 방식으로 처리됩니다. 물론 이러한 방식으로 연산을 수행해도 그 결과는 앞서 배열간 연산으로 얻었던 것과 동일합니다. 즉 배열 r의 값들을 반복형 구문으로 출력해보면 그 내용은 위에서 본 것과 완전히 동일합니다. 따라서 일단 여기까지의 결과를 보면 배열들에 대한 연산에 있어서 배열간 연산과 반복형 구문에 의한 연산 사이에는 별다른 차이가 없고 둘 다 동일한 결과를 생산하는 것으로 보입니다. 그런데 사실은 &quot;아무런 차이가 없다&quot;고 볼 수는 없습니다. 실제로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;두 방식 사이에는 연산에 걸리는 시간에 있어서 차이가 존재&lt;/b&gt;&lt;/span&gt;합니다. 다만 이러한 차이는 배열들의 원소 갯수가 적을 경우에는 거의 나타나지 않습니다. 반대로 얘기하면 &lt;b&gt;배열들의 원소 갯수가 크면 클수록 그 차이가 점점 두드러지게 나타난다&lt;/b&gt;고 보면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 이러한 차이를 살펴보기 위해서 앞서 했던 두가지 방식의 연산 각각에 대하여 &lt;b&gt;배열들의 원소 갯수를 대폭 늘리고 연산에 걸리는 시간도 정량적으로 측정&lt;/b&gt;해봅시다. 그 과정은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;n = 10000000&lt;/b&gt; &lt;br /&gt;a&amp;nbsp;=&amp;nbsp;RANDOMU(-1,&amp;nbsp;n)*100 &lt;br /&gt;b&amp;nbsp;=&amp;nbsp;RANDOMU(-2,&amp;nbsp;n)*100 &lt;br /&gt;c&amp;nbsp;=&amp;nbsp;RANDOMU(-3,&amp;nbsp;n)*100 &lt;br /&gt;&lt;br /&gt;&lt;b&gt;TIC&lt;/b&gt; &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;a/SQRT(b+c) &lt;br /&gt;&lt;b&gt;TOC&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;TIC&lt;/b&gt; &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;FLTARR(n) &lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;n-1&amp;nbsp;DO&amp;nbsp;r[j]&amp;nbsp;=&amp;nbsp;a[j]/SQRT(b[j]+c[j]) &lt;br /&gt;&lt;b&gt;TOC&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 두가지 방식의 연산 과정들 자체는 그대로이지만 각 연산 과정의 앞뒤에 TIC, TOC 명령을 삽입하여 시간을 측정하도록 하였습니다. 또한 배열들의 원소 갯수를 기존의 10에서 10000000으로 대폭 늘렸습니다. 이렇게 하면 두가지 방식의 연산 각각에 대한 소요시간이 측정되어 출력될 것입니다. 다만 배열들의 원소 갯수가 매우 크므로 매 회차마다 결과값들을 출력하는 과정은 생략하였습니다. 어쨌든 위의 내용을 제 PC의 IDL에서 실행해본 결과는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.019999981&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;1.0020001&amp;nbsp;seconds.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 첫번째 방식 즉 배열간 연산의 경우는 0.02초가 걸린 반면 두번째 방식 즉 반복형 구문을 사용한 연산의 경우에는 1.00초 정도가 걸렸습니다. 물론 이러한 수치는 실행할 때마다 다를 수 있고 여러분의 PC에서도 다를 수 있겠지만, 두번째 방식이 시간이 더 걸린다는 것은 변함이 없을 것입니다. 이게 수치상으로는 얼마 안되어 보일 수 있지만 배수로 따지면 두번째 방식이 약 50배 정도 더 느린 셈이므로 상당히 큰 차이입니다. 어쨌든 이러한 비교 결과를 보면 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;배열간 연산에 비해서 반복형 구문에 의한 연산이 더 많은 시간이 걸린다&lt;/b&gt;&lt;/span&gt;는 것을 확인할 수 있습니다. 따라서 배열들에 대하여 연산을 수행하고 결과를 얻어야 하는 경우에는 웬만하면 배열간 연산의 방식으로 처리하는 것이 더 효율적이라는 것을 염두에 둘 필요가 있습니다. 물론 반복형 구문을 사용하는 방식으로도 동일한 결과를 얻을 수는 있지만, 데이터의 양이 매우 클 경우에는 시간이 더 걸릴 수 밖에 없다는 점을 유의해야 합니다. 실제로 &lt;b&gt;대용량의 데이터에 대하여 복잡한 연산을 수행하게 될 경우에는 두가지 방식 사이의 차이가 굉장히 크게 나타날 수도 있다&lt;/b&gt;는 것을 염두에 둘 필요가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 다음 회차에서는 이러한 차이를 확인할 수 있는 다른 예제를 살펴보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;* 이 글이 도움이 되었다면 게시물에 대하여 공감 버튼(하트 모양) 클릭 및 블로그 구독도 해주시면 더 큰 힘이 됩니다. 감사합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IDL/Programming</category>
      <author>이상우_IDL</author>
      <guid isPermaLink="true">https://swrush.tistory.com/827</guid>
      <comments>https://swrush.tistory.com/827#entry827comment</comments>
      <pubDate>Mon, 23 Feb 2026 16:53:20 +0900</pubDate>
    </item>
    <item>
      <title>TIC, TOC 명령을 활용한 시간 측정 방법</title>
      <link>https://swrush.tistory.com/826</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 IDL에서 특정한 프로세스가 돌아가는데 걸리는 시간을 측정할 때 사용하는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;TIC, TOC 명령들&lt;/b&gt;&lt;/span&gt;에 관하여 간략히 살펴볼까 합니다. 사실 TIC, TOC 명령들은 제가 이 블로그에서 올린 몇몇 게시물들에서도 이미 여러번 사용한 바 있습니다. 사용 방법은 매우 간단하며 마치 스톱워치처럼 사용하면 됩니다. 즉 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;TIC 명령을 실행하면 시간 측정이 시작되고 TOC 명령을 실행하면 시간 측정이 멈추면서 그때까지 경과한 시간을 초 단위로 표시&lt;/b&gt;&lt;/span&gt;해줍니다. 먼저 다음과 같이 IDL의 명령 프롬프트에서 간단히 시도해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IDL&amp;gt;&amp;nbsp;TIC &lt;br /&gt;IDL&amp;gt;&amp;nbsp;TOC &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;3.4210000&amp;nbsp;seconds.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 TIC 명령을 실행하고 어느 정도 이후에 TOC 명령을 실행하면 경과 시간 즉 &lt;b&gt;TIC 명령이 실행된 순간부터 TOC 명령이 실행된 순간까지 경과된 시간을 초 단위로 측정&lt;/b&gt;하여 출력해줍니다. 명령 프롬프트 뿐 아니라 프로그램 내에서도 특정한 프로세스가 실행되는데 소요되는 시간을 측정할 목적으로 사용할 수 있습니다. 이러한 예제를 보면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a = FINDGEN(10001) &lt;br /&gt;n&amp;nbsp;=&amp;nbsp;N_ELEMENTS(a)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; TIC&lt;/b&gt;&lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;n-1&amp;nbsp;DO&amp;nbsp;PRINT,&amp;nbsp;j,&amp;nbsp;a[j],&amp;nbsp;SQRT(a[j]) &lt;br /&gt;&lt;b&gt;TOC&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 &lt;b&gt;반복형 구문이 끝까지 실행되기까지 총 어느 정도의 시간이 걸리는가를 정량적으로 확인&lt;/b&gt;하기 위하여 TIC, TOC 명령을 사용하였습니다. 위의 내용을 실행하면 총 10001회에 걸친 반복 작업에 의하여 매 회차마다 출력이 진행되고, 반복 작업이 모두 종료된 이후에는 측정 시간이 표시될 것입니다. 출력 내용의 맨 뒷부분만 보면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9997&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9997.00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;99.9850 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9998&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9998.00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;99.9900 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9999&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;9999.00&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;99.9950 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;10000&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;10000.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;100.000 &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;1.6440001&amp;nbsp;seconds.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 1.644초가 걸린 것으로 확인됩니다. 물론 이러한 수치는 프로그램을 실행할 때마다 조금씩 달라질 수 있으며, 여러분의 PC에서는 아마 다르게 측정될 것입니다. 어쨌든 이와 같은 특성 때문에 IDL 프로그램을 작성하면서 특정한 프로세스에 대하여 구동 시간을 측정할 목적으로 유용하게 사용될 수 있습니다. 그러면 TIC, TOC 명령의 사용법에 관하여 한 단계 더 들어가보겠습니다. 이번 예제는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ni&amp;nbsp;=&amp;nbsp;1000000 &lt;br /&gt;nj&amp;nbsp;=&amp;nbsp;10 &lt;br /&gt;a&amp;nbsp;=&amp;nbsp;FINDGEN(ni,&amp;nbsp;nj) &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;FLTARR(ni,&amp;nbsp;nj) &lt;br /&gt;&lt;b&gt;TIC&lt;/b&gt; &lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;nj-1&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp; FOR i = 0, ni-1 DO BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r[i,&amp;nbsp;j]&amp;nbsp;=&amp;nbsp;a[i,&amp;nbsp;j]^0.6+a[i,&amp;nbsp;j]^0.3 &lt;br /&gt;&amp;nbsp; ENDFOR &lt;br /&gt;ENDFOR &lt;br /&gt;&lt;b&gt;TOC&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 예제는 이중 루프의 형태를 띄는 작업입니다. 여기서 ni는 1000000이고 nj는 10이므로 전체적인 반복 횟수는 1000000x10 즉 10000000회(천만 회)가 됩니다. 세부적으로는 안쪽 루프인 i 루프가 1000000회 반복 그리고 바깥쪽 루프인 j 루프가 10회 반복을 하게 됩니다. 그리고 이중 루프 작업의 전체적인 소요 시간을 측정하기 위하여 TIC, TOC 명령을 사용하였습니다. 이렇게 실행을 하면 측정된 시간이 출력됩니다. 제 컴퓨터에서는 다음과 같이 약 1.5초 정도가 걸리는 것으로 출력되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;1.4879999&amp;nbsp;seconds.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 &lt;b&gt;이중 루프의 전체적인 작업 시간 뿐 아니라 안쪽 루프에 대한 작업 시간도 매회 측정&lt;/b&gt;하고 싶은 경우를 가정해봅시다. 즉 안쪽 루프인 i 루프는 1000000회의 반복 작업을 하는데 그 소요 시간을 측정하는 것입니다. 그러면 총 10회에 걸쳐 안쪽 루프의 소요 시간을 측정하게 됩니다. 이를 위해서는 다음과 같이 TIC, TOC 명령을 j 루프 안쪽에서 추가로 사용해주면 될 것으로 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ni&amp;nbsp;=&amp;nbsp;1000000 &lt;br /&gt;nj&amp;nbsp;=&amp;nbsp;10 &lt;br /&gt;a&amp;nbsp;=&amp;nbsp;FINDGEN(ni,&amp;nbsp;nj) &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;FLTARR(ni,&amp;nbsp;nj) &lt;br /&gt;&lt;b&gt;TIC&lt;/b&gt; &lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;nj-1&amp;nbsp;DO&amp;nbsp;BEGIN&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &lt;b&gt;TIC&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;FOR&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;ni-1&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r[i,&amp;nbsp;j]&amp;nbsp;=&amp;nbsp;a[i,&amp;nbsp;j]^0.6+a[i,&amp;nbsp;j]^0.3 &lt;br /&gt;&amp;nbsp;&amp;nbsp;ENDFOR&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &lt;b&gt;TOC&lt;/b&gt;&lt;br /&gt;ENDFOR &lt;br /&gt;&lt;b&gt;TOC&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 안쪽 루프에 대해서도 시간 측정을 할 수 있도록 TIC, TOC 명령들을 추가한 다음 다시 실행을 해봅시다. 제가 이 내용을 실행하여 얻은 출력 내용을 보면 다음과 같았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14400005&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14499998&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14100003&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.15599990&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.15000010&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14499998&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14599991&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.15000010&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14400005&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14599991&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14599991&amp;nbsp;seconds.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 이 내용을 보면 10회에 걸쳐 바깥쪽 루프가 돌 때마다 안쪽 루프의 소요 시간이 측정되어 출력된 것을 확인할 수 있습니다. 매 회당 약 0.14~0.15초인데, 앞서 전체 작업의 소요 시간이 약 1.4~1.5초였던 것을 감안하면 맞는 수치인 것으로 보입니다. 그런데 출력 내용의 마지막 두 줄을 보면 그 수치가 서로 완전히 동일합니다. 원래 맨 마지막 출력 내용은 이중 루프의 전체 소요 시간이 되도록 하였는데, 그 의도와는 전혀 다른 결과입니다. 이것은 여기서 사용된 TIC, TOC 명령들의 시작과 끝이 서로 뒤섞이면서 발생한 문제입니다. 즉 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;TOC 명령이 측정하는 시간은 무조건 바로 이전 가장 최근에 TIC 명령이 실행된 시점을 기준으로 한다&lt;/b&gt;&lt;/span&gt;는 특성 때문입니다. 따라서 여기서 맨 마지막에 사용된 TOC 명령은 원래 의도는 맨 처음(이중 루프 작업의 시작 직전)에 명시된 TIC 명령을 시점으로 인식하도록 한 것이었으나, 실제로는 안쪽 루프의 맨 마지막 10회차에서 사용된 TIC 명령이 그 시점으로 간주되는 바람에 이와 같이 우리의 의도와는 다른 측정 결과를 산출한 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 &lt;b&gt;TIC, TOC 명령이 서로 올바르게 짝지어지도록 하여 이러한 혼란을 방지할 수 있는 방법&lt;/b&gt;이 있다면 좋을 것 같은데, 다행히도 그러한 방법은 있습니다. 바로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;TIC, TOC 명령의 쌍이 서로 구분되도록 고유의 ID를 부여하는 기능&lt;/b&gt;&lt;/span&gt;을 활용하면 됩니다. 이러한 기능을 활용하여 위의 내용을 수정해보면 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ni&amp;nbsp;=&amp;nbsp;1000000 &lt;br /&gt;nj&amp;nbsp;=&amp;nbsp;10 &lt;br /&gt;a&amp;nbsp;=&amp;nbsp;FINDGEN(ni,&amp;nbsp;nj) &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;FLTARR(ni,&amp;nbsp;nj) &lt;br /&gt;&lt;b&gt;clk_total = TIC('for the entire process')&lt;/b&gt; &lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;nj-1&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;TIC&lt;/b&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;FOR&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;ni-1&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r[i,&amp;nbsp;j]&amp;nbsp;=&amp;nbsp;a[i,&amp;nbsp;j]^0.6+a[i,&amp;nbsp;j]^0.3 &lt;br /&gt;&amp;nbsp; ENDFOR &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;TOC&lt;/b&gt; &lt;br /&gt;ENDFOR &lt;br /&gt;&lt;b&gt;TOC,&amp;nbsp;clk_total&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 이중 루프의 전체 소요 시간을 측정하는데 있어서 TIC, TOC 명령이 사용된 새로운 방식에 주목해야 합니다. 특히 여기서는 &lt;b&gt;TIC 명령을 함수의 형태로 사용&lt;/b&gt;하였습니다. 먼저 TIC 함수 내에 명시된 'for the entire process'는 유저가 지정한 문자열이며 나중에 TOC 명령이 시간을 출력할 때 함께 표시되도록 할 목적으로 부가적으로 사용한 것입니다. 그리고 &lt;b&gt;TIC 함수의 좌변&lt;/b&gt;에 있는 clk_total이 바로 &lt;b&gt;고유 ID의 역할&lt;/b&gt;을 합니다. 그래서 맨 마지막에서 사용된 TOC 명령에서 바로 이 clk_total이 인수로 사용된 것을 함께 주목하면 됩니다. 즉 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;TIC 함수를 사용하면서 고유 ID를 정의하고 TOC 명령에서 이를 인수로 활용하도록&lt;/b&gt;&lt;/span&gt; 하면 됩니다. 이렇게 하면 이 TOC 명령은 시간 측정의 시점을 clk_total에 해당되는 TIC 명령이 실행된 시점으로 정확히 인식하게 됩니다. 이와 같은 수정 사항을 반영하여 다시 실행해보면 출력 결과는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14499998&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14299989&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14000010&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14199996&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14600015&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14299989&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14199996&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14300013&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14599991&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed:&amp;nbsp;0.14599991&amp;nbsp;seconds. &lt;br /&gt;% Time elapsed for the entire process: 1.4359999 seconds.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 내용을 보면 안쪽 루프들에 대한 소요 시간 및 전체 작업의 소요 시간이 명확히 구분되어 측정된 것을 확인할 수 있습니다. 따라서 &lt;b&gt;프로그램 내에서 다수의 부분 프로세스들에 대하여 시간 측정을 해야 할 경우&lt;/b&gt;에는 이와 같이 &lt;b&gt;각각의 TIC, TOC 명령의 쌍들에 대하여 고유 ID를 부여하여 활용&lt;/b&gt;하면 시간 측정 결과의 혼란을 막을 수 있습니다. 그리고 이왕이면 안쪽 루프 작업들에 대한 시간 측정에 대해서도 비슷한 방식으로 고유 ID를 부여하여 구분해주는 것이 더 바람직할 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ni&amp;nbsp;=&amp;nbsp;1000000 &lt;br /&gt;nj&amp;nbsp;=&amp;nbsp;10 &lt;br /&gt;a&amp;nbsp;=&amp;nbsp;FINDGEN(ni,&amp;nbsp;nj) &lt;br /&gt;r&amp;nbsp;=&amp;nbsp;FLTARR(ni,&amp;nbsp;nj) &lt;br /&gt;&lt;b&gt;clk_total&amp;nbsp;=&amp;nbsp;TIC('for&amp;nbsp;the&amp;nbsp;entire&amp;nbsp;process')&lt;/b&gt; &lt;br /&gt;FOR&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;nj-1&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;clk_inside&amp;nbsp;=&amp;nbsp;TIC('for&amp;nbsp;inner&amp;nbsp;loop&amp;nbsp;'+STRTRIM(STRING(j),&amp;nbsp;2))&lt;/b&gt; &lt;br /&gt;&amp;nbsp;&amp;nbsp;FOR&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0,&amp;nbsp;ni-1&amp;nbsp;DO&amp;nbsp;BEGIN &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;r[i,&amp;nbsp;j]&amp;nbsp;=&amp;nbsp;a[i,&amp;nbsp;j]^0.6+a[i,&amp;nbsp;j]^0.3 &lt;br /&gt;&amp;nbsp; ENDFOR &lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;b&gt;TOC,&amp;nbsp;clk_inside&lt;/b&gt; &lt;br /&gt;ENDFOR &lt;br /&gt;&lt;b&gt;TOC,&amp;nbsp;clk_total&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 안쪽 루프들에 대해서도 비슷한 처리를 해주면 출력 결과는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;%&amp;nbsp;Time&amp;nbsp;elapsed&amp;nbsp;for&amp;nbsp;inner&amp;nbsp;loop&amp;nbsp;0:&amp;nbsp;0.14599991&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed&amp;nbsp;for&amp;nbsp;inner&amp;nbsp;loop&amp;nbsp;1:&amp;nbsp;0.13900018&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed&amp;nbsp;for&amp;nbsp;inner&amp;nbsp;loop&amp;nbsp;2:&amp;nbsp;0.14399981&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed&amp;nbsp;for&amp;nbsp;inner&amp;nbsp;loop&amp;nbsp;3:&amp;nbsp;0.14400005&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed&amp;nbsp;for&amp;nbsp;inner&amp;nbsp;loop&amp;nbsp;4:&amp;nbsp;0.15000010&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed&amp;nbsp;for&amp;nbsp;inner&amp;nbsp;loop&amp;nbsp;5:&amp;nbsp;0.14599991&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed&amp;nbsp;for&amp;nbsp;inner&amp;nbsp;loop&amp;nbsp;6:&amp;nbsp;0.14400005&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed&amp;nbsp;for&amp;nbsp;inner&amp;nbsp;loop&amp;nbsp;7:&amp;nbsp;0.14499998&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed&amp;nbsp;for&amp;nbsp;inner&amp;nbsp;loop&amp;nbsp;8:&amp;nbsp;0.14100003&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed&amp;nbsp;for&amp;nbsp;inner&amp;nbsp;loop&amp;nbsp;9:&amp;nbsp;0.14499998&amp;nbsp;seconds. &lt;br /&gt;%&amp;nbsp;Time&amp;nbsp;elapsed&amp;nbsp;for&amp;nbsp;the&amp;nbsp;entire&amp;nbsp;process:&amp;nbsp;1.4449999&amp;nbsp;seconds.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력 내용을 보면 측정된 시간들이 각각 어떤 프로세스에 대한 것인가를 명확하게 구분하여 확인할 수 있습니다. 따라서 TIC, TOC 명령은 단순하게 사용할 수도 있지만, 방금 소개한 것처럼 고유의 ID를 부여하면 다수의 TIC, TOC 쌍들이 사용될 때 서로를 구분할 수 있으므로 좀 더 다양한 방식의 활용이 가능하다는 점을 참조해두시면 좋을 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;* 이 글이 도움이 되었다면 게시물에 대하여 공감 버튼(하트 모양) 클릭 및 블로그 구독도 해주시면 더 큰 힘이 됩니다. 감사합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>IDL/Miscellaneous</category>
      <author>이상우_IDL</author>
      <guid isPermaLink="true">https://swrush.tistory.com/826</guid>
      <comments>https://swrush.tistory.com/826#entry826comment</comments>
      <pubDate>Thu, 12 Feb 2026 15:28:24 +0900</pubDate>
    </item>
  </channel>
</rss>