<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Origin of Ray</title>
  
  <subtitle>Lift the fog of the Internet together</subtitle>
  <link href="https://sunra.top/en/atom.xml" rel="self"/>
  
  <link href="https://sunra.top/en/"/>
  <updated>2026-06-13T06:03:37.139Z</updated>
  <id>https://sunra.top/en/</id>
  
  <author>
    <name>Ray Sun</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Application of State Compression in Algorithms</title>
    <link href="https://sunra.top/en/posts/338aebbd/"/>
    <id>https://sunra.top/en/posts/338aebbd/</id>
    <published>2023-06-21T00:47:43.000Z</published>
    <updated>2026-06-13T06:03:37.139Z</updated>
    
    <content type="html"><![CDATA[<p>In computer algorithms, state compression is an optimization technique that reduces memory usage and improves program efficiency by compressing some state information into smaller data structures. Typically, state compression is applied to algorithms that need to handle a large amount of state, such as search, dynamic programming, etc. Common approaches to state compression include using data structures such as bitwise operations, hash tables, arrays, etc. to store state information. These methods can significantly reduce the time and space complexity of the algorithm and improve the execution efficiency of the algorithm.</p><span id="more"></span><p>Simply put, state compression is a more subtle way to reduce the CURD of various states during the operation of an algorithm, thus reducing both time and space complexity.</p><p>Let’s use a problem from leetcode to demonstrate the use of state compression in dynamic programming:</p><p>This is the stem of the question:</p><p>You are given two sets of points, where the first set has size1 points and the second set has size2 points, and size1 &gt;= size2.</p><p>The cost of connection between any two points is given by a matrix of size1 x size2, where cost[i][j] is the cost of connection between point i in the first group and point j in the second group. Two groups of points are said to be connected if each point in both groups is connected to one or more points in the other group. In other words, each point in the first group must be connected to at least one point in the second group, and each point in the second group must be connected to at least one point in the first group.</p><p>Returns the minimum cost required to connect the two sets of points.</p><p>This topic is also a dichotomous graph problem, but it is not the same as<a href="https://sunra.top/posts/5352/">匈牙利算法</a>The problem solved is different in that the pairing here is not one-to-one, but many-to-many, as long as each point is connected to a point in another graph</p><p>Let’s look at the solution to this problem</p><p>Let the first set of points be <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>i</mi><mi>z</mi><msub><mi>e</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">size_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.80952em;vertical-align:-0.15em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> and the second set of points be <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mi>i</mi><mi>z</mi><msub><mi>e</mi><mn>2</mn></msub></mrow><annotation encoding="application/x-tex">size_2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.80952em;vertical-align:-0.15em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>. Depending on the range of the data, we can use the binary number s to represent a point set, where the kth bit of s is 1 to indicate that the kth point is in point set s, and the kth bit of s is 0 to indicate that the kth point is not in point set s. Use dp[i][s] to denote the first iii points of the first set (the first i points are the 0th,1st,2nd,…,i-1st points). ,i-1 points) with the minimum connectivity cost of the second set of points s (since size1 ≥ size2, the second set is taken as the set of points) in four cases:</p><ul><li><p>i=0 and s=0:<br />Both sets of points are empty, so the minimum connectivity cost is dp[0][0] = 0.</p></li><li><p>i=0 and s≠0<br />The points in the first group are empty and the points in the second group are not empty, so they cannot be connected, such that dp[0][s] = ∞.</p></li><li><p>i≠0 and s=0:<br />The points in the first group are not empty, and the points in the second group are empty, so they cannot be connected, such that dp[i][0] = ∞.</p></li><li><p>i≠0 and s≠0<br />Consider the first set of i-1 points connected to the kth point of the second set of points s. Using <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>s</mi><mrow><mo>−</mo><mi>k</mi></mrow></msub></mrow><annotation encoding="application/x-tex">s_{-k}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.638891em;vertical-align:-0.208331em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361079999999999em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.208331em;"><span></span></span></span></span></span></span></span></span></span> to denote the remaining set of points after the kth point is removed from the point set s, then the connectivity cost c has three cases:</p><ul><li><p>the kth point of the second set of points s is no longer connected to other points, then c = dp[i][s-k] + cost[i-1][k];</p></li><li><p>the first group of points i-1 is no longer connected to other points, then c = dp[i-1][s] + cost[i-1][k];</p></li><li><p>The first set of points i-1 and the kth point of the second set of points s are no longer connected to other points, then c=dp[i-1][s-k]+cost[i-1][k].</p></li></ul></li></ul><p>Enumerate the first set of points i-1 connected to any point k ∈ s in the second set of points s. Then the state transfer equation is as follows:</p><p>dp[i][s]=min⁡k∈s{min⁡{dp[i][s−k],dp[i−1][s],dp[i−1][s−k]}+cost[i−1][k]}</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> connectTwoGroups = <span class="keyword">function</span>(<span class="params">cost</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> size1 = cost.<span class="property">length</span>;</span><br><span class="line">    <span class="keyword">const</span> size2 = cost[<span class="number">0</span>].<span class="property">length</span>;</span><br><span class="line">    <span class="keyword">const</span> m = <span class="number">1</span> &lt;&lt; size2;</span><br><span class="line">    <span class="keyword">const</span> dp = <span class="title class_">Array</span>.<span class="title function_">from</span>(<span class="title class_">Array</span>(size1 + <span class="number">1</span>), <span class="function">() =&gt;</span> <span class="keyword">new</span> <span class="title class_">Array</span>(m).<span class="title function_">fill</span>(<span class="title class_">Number</span>.<span class="property">MAX_SAFE_INTEGER</span> / <span class="number">2</span>));</span><br><span class="line"></span><br><span class="line">    dp[<span class="number">0</span>][<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">1</span>; i &lt;= size1; i++) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">let</span> s = <span class="number">0</span>; s &lt; m; s++) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">let</span> k = <span class="number">0</span>; k &lt; size2; k++) &#123;</span><br><span class="line">            <span class="keyword">if</span> ((s &amp; (<span class="number">1</span> &lt;&lt; k))= <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            dp[i][s] = <span class="title class_">Math</span>.<span class="title function_">min</span>(dp[i][s], dp[i][s ^ (<span class="number">1</span> &lt;&lt; k)] + cost[i - <span class="number">1</span>][k]);</span><br><span class="line">            dp[i][s] = <span class="title class_">Math</span>.<span class="title function_">min</span>(dp[i][s], dp[i - <span class="number">1</span>][s] + cost[i - <span class="number">1</span>][k]);</span><br><span class="line">            dp[i][s] = <span class="title class_">Math</span>.<span class="title function_">min</span>(dp[i][s], dp[i - <span class="number">1</span>][s ^ (<span class="number">1</span> &lt;&lt; k)] + cost[i - <span class="number">1</span>][k]);</span><br><span class="line">        &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> dp[size1][m - <span class="number">1</span>];</span><br><span class="line">&#125;;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="compression-on-data-structure"><a class="markdownIt-Anchor" href="#compression-on-data-structure"></a> Compression on data structure</h2><p>The dynamic programming in this algorithm needs no further explanation, in fact, it also contains state compression, for example, compressing a boolean array into a binary number is a common practice, which may not see much improvement in terms of space, but in this problem, we need to represent the state with a boolean array and use this state as the key, then we can only use map to store the key-value pairs, but if we use binary numbers as key, we can use arrays to store key-value pairs.</p><h2 id="eliminate-storage-of-useless-intermediate-states"><a class="markdownIt-Anchor" href="#eliminate-storage-of-useless-intermediate-states"></a> Eliminate storage of useless intermediate states</h2><p>Another type of state compression refers to identifying useless states and eliminating them</p><p>The calculation of dp[i][∗] for the transfer equation is only related to dp[i-1][∗] and dp[i][∗], so we can save space by using only one-dimensional arrays to keep it.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> connectTwoGroups = <span class="keyword">function</span>(<span class="params">cost</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> size1 = cost.<span class="property">length</span>;</span><br><span class="line">    <span class="keyword">const</span> size2 = cost[<span class="number">0</span>].<span class="property">length</span>;</span><br><span class="line">    <span class="keyword">const</span> m = <span class="number">1</span> &lt;&lt; size2;</span><br><span class="line">    <span class="keyword">const</span> dp1 = <span class="keyword">new</span> <span class="title class_">Array</span>(m).<span class="title function_">fill</span>(<span class="title class_">Number</span>.<span class="property">MAX_SAFE_INTEGER</span> / <span class="number">2</span>);</span><br><span class="line">    <span class="keyword">const</span> dp2 = <span class="keyword">new</span> <span class="title class_">Array</span>(m);</span><br><span class="line">    </span><br><span class="line">    dp1[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">1</span>; i &lt;= size1; i++) &#123;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">let</span> s = <span class="number">0</span>; s &lt; m; s++) &#123;</span><br><span class="line">        dp2[s] = <span class="title class_">Number</span>.<span class="property">MAX_SAFE_INTEGER</span> / <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">let</span> k = <span class="number">0</span>; k &lt; size2; k++) &#123;</span><br><span class="line">            <span class="keyword">if</span> ((s &amp; (<span class="number">1</span> &lt;&lt; k))= <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">continue</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            dp2[s] = <span class="title class_">Math</span>.<span class="title function_">min</span>(dp2[s], dp2[s ^ (<span class="number">1</span> &lt;&lt; k)] + cost[i - <span class="number">1</span>][k]);</span><br><span class="line">            dp2[s] = <span class="title class_">Math</span>.<span class="title function_">min</span>(dp2[s], dp1[s] + cost[i - <span class="number">1</span>][k]);</span><br><span class="line">            dp2[s] = <span class="title class_">Math</span>.<span class="title function_">min</span>(dp2[s], dp1[s ^ (<span class="number">1</span> &lt;&lt; k)] + cost[i - <span class="number">1</span>][k]);</span><br><span class="line">        &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        dp1.<span class="title function_">splice</span>(<span class="number">0</span>, m, ...dp2);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> dp1[m - <span class="number">1</span>];</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;In computer algorithms, state compression is an optimization technique that reduces memory usage and improves program efficiency by compressing some state information into smaller data structures. Typically, state compression is applied to algorithms that need to handle a large amount of state, such as search, dynamic programming, etc. Common approaches to state compression include using data structures such as bitwise operations, hash tables, arrays, etc. to store state information. These methods can significantly reduce the time and space complexity of the algorithm and improve the execution efficiency of the algorithm.&lt;/p&gt;</summary>
    
    
    
    <category term="Algorithm" scheme="https://sunra.top/en/categories/Algorithm/"/>
    
    
  </entry>
  
  <entry>
    <title>Management Methodology for Technical People (VI) - Task Management</title>
    <link href="https://sunra.top/en/posts/5d2fbe1a/"/>
    <id>https://sunra.top/en/posts/5d2fbe1a/</id>
    <published>2023-06-17T23:53:30.000Z</published>
    <updated>2026-06-13T06:03:37.130Z</updated>
    
    <content type="html"><![CDATA[<p>To get things done and get results is the landing point of management, and it is also the most important standard and basis to verify whether the management planning is reasonable and the team building is effective.</p><p>Come from work and go to work. Never create a mechanism for the sake of creating a mechanism; every mechanism must have practical value.</p><p>Since mechanisms are scenario-specific, when the scenario changes, the mechanism has to be upgraded as well. Revisiting and learning the mechanism means extra overhead, so each mechanism has a cost to maintain, and if it is not upgraded and updated as the scenario changes, it will become a meaningless mechanism, and over time it will become common: whatever mechanism is available, but the execution is not good</p><span id="more"></span><h3 id="stage"><a class="markdownIt-Anchor" href="#stage"></a> Stage</h3><ul><li><p>Before the event</p><p>The most important question for managers to answer is what needs to be done, which one to do first and which one to do later, that is, sorting out the priority of tasks, which corresponds to “prioritization” in management</p></li><li><p>In the Matter</p><p>Ensuring that things move forward according to plan, which translates into “effective execution” or “project management” in the narrow sense</p></li><li><p>After the fact</p><p>To consciously summarize the lessons learned and form some “rules” and “practices” so that similar work can be done better and more smoothly in the future, corresponding to the management of the &quot;process mechanism &quot;</p></li></ul><h3 id="element-eg-in-array-in-programming-in-programming"><a class="markdownIt-Anchor" href="#element-eg-in-array-in-programming-in-programming"></a> element (e.g. in array, in programming, in programming)</h3><ul><li><p>slight or important, urgent or non-urgent</p><p>For each specific team, there is a limit to the amount of work that can be done at the moment, and simply increasing concurrency does not make the team’s output more efficient</p><ul><li><p>Prioritized decision-making steps</p><ul><li><p>Critical Emergency Quadrant</p></li><li><p>How to determine if a job is important and urgent</p><p>If you do, does it benefit a lot, the greater the benefit the more important<br />If not, is it a great loss, the greater the loss, the more urgent</p></li><li><p>Common scenarios</p><p>Divide daily work into two cases: one is planned and one is unplanned<br />For the planned work, you need to focus on how much value and benefit it has in a planning cycle, and schedule in tasks that are of sufficient value to continuously advance<br />For unplanned work, since it is an unexpected situation, the first step is to judge the interruption i.e. there are arrangements to immediately follow up the new situation. Interrupting an existing arrangement will definitely affect the work at hand, that is, it will affect what would have been gained.</p></li><li><p>Steps</p><p>First of all, judge the priority of the work to specify their own plans. For the work within the plan, see if the benefits are large enough, the greater the benefits the more important, the greater the benefits, the greater the need to give matching priorities, resources and attention; relatively small benefits, put into the todo list, as a to-do task<br />For unplanned work, see if the loss is large enough, the larger the loss, the more urgent it is. If the loss is large enough, the task is scheduled as urgent, with “stop loss” as the core purpose. If the loss is manageable, put it in the list of planned work, and use the gain as the measurement indicator.</p></li></ul></li><li><p>Decision Points</p><ul><li><p>Goals need to be consistent</p><p>As mentioned earlier, judging whether a task is important by looking at the benefits, what frame of reference should be used to measure the benefits?<br />The answer is goals, which contain our most important demands and expectations over a period of time, and are the axes of measurement that affect the size of our work gains. The clearer the goals, the stronger our sense of direction at critical moments.</p></li><li><p>The evaluation latitude of the task is flexible</p><p>For a task, the three elements of progress, quality and effectiveness can be mutually exclusive, so when disassembling a task, different expectations of progress, different requirements for quality and different expectations for effectiveness can lead to changes in expected time and priority</p></li><li><p>Communication is indispensable</p><p>Superiors are more likely to tell you what they want than to offer to tell you what they are willing to trade, not exactly because they are “profit-oriented,” but because it is not their job to assess the impact and offer the appropriate solution, which is something you know and can do.<br />Superiors can not judge how big the impact on your i.e. arrangement, you need to give an assessment, if you do not say anything, the default is no impact.</p></li></ul></li></ul></li><li><p>Process Management</p><ul><li><p>How to ensure effective project execution</p><ul><li><p>Sufficient Conditions Perspective</p><p>Just list all the points for effective execution and follow them, but it’s not realistic</p></li><li><p>Necessity Perspective</p><p>Although we cannot give all the conditions for effective project implementation, we can certainly put forward some points in long-term project management, and as long as these points are not achieved, the project will be difficult to be implemented effectively</p></li></ul></li><li><p>Four Barriers to Effective Execution</p><ul><li><p>unclear objectives</p><ul><li>Unclear and unmeasurable goals</li><li>Objectives are not aligned and have deviations</li><li>The target has changed and there are no synchronized related people</li></ul></li><li><p>Absence of General Manager</p><ul><li><p>Three questions</p><ul><li>Is there a clear leader for each team involved in the project</li><li>The person in charge and all project team members, are they clear about the individual aspects of the person in charge</li><li>Whether the project has a sole general manager and whether the general manager is effective</li></ul></li><li><p>Two easy areas of ambiguity</p><ul><li>Inconsistent understanding of “responsibility” among principals</li><li>Total person in charge is invalid or missing</li></ul></li></ul></li><li><p>Lack of mechanism for effective operation</p><ul><li><p>Question</p><ul><li>Some managers have seen some good people’s excellent performance, too superstitious people’s initiative and career level, once the problem, always feel that people can not. In fact, the ability level of team members is normally distributed, even if it is true that people can not, from not to line also need the process, at this time is the time when managers should do something</li><li>When people don’t work, they like to use processes and mechanisms. As a result, managers develop a full set of processes for their teams to follow, and because of the high cost of learning and implementation, it is painful for employees to follow, thus causing the processes and mechanisms to sleep</li></ul></li><li><p>Summary</p><ul><li>Too much reliance on human initiative, lack of process and mechanism</li><li>Although there is a mechanism, there is no one to monitor the implementation</li><li>Employees are reluctant to perform even though there is supervision of the implementation</li></ul></li></ul></li><li><p>Inadequate communication</p><ul><li>Lack of proactive awareness and communication</li><li>Insufficient awareness of notification and failure to notify all relevant personnel</li><li>Insufficient awareness of the closed loop, broadcast out, the other side received by default</li></ul></li></ul></li><li><p>The four elements of effective execution</p><ul><li>Clarity of purpose</li><li>Clear responsibility</li><li>Sound mechanism</li><li>Communication in place</li></ul></li></ul></li><li><p>Process Mechanism</p><p>On the one hand, many managers hope that a lot of management work can be guaranteed through processes and mechanisms to improve their management efficiency; on the other hand, they are at a loss because a large number of processes and mechanisms are lying in the document and sleeping.</p><ul><li><p>Steps of process mechanism establishment</p><p>As managers, trying to get employees to share the work we have at hand either by laddering or by process mechanisms</p><ul><li>The so-called rely on the gradient, that is, the team has a very high degree of competence within the people who can help us to deal with this matter</li><li>The so-called relying mechanism is to design a set of programs to specifically respond to the problems that arise in a certain scenario, and use this set of programs to guide employees to do this kind of work</li><li>If the original intention is talent development, then it is reasonable to go and bring employees along to develop the ladder. But if the original intention is to reduce the burden of managers, that instead should rely on the mechanism. And, training echelon is always far water, rely on the mechanism to solve the problem at hand is near thirst, how good the echelon can not mention the role of the mechanism</li></ul></li><li><p>The process of establishing the authorization mechanism</p><ul><li><p>Clearly defined objectives</p><p>Clarify what problem in what scenario the change mechanism is intended to solve.<br />One of the major characteristics of the mechanisms is that the scenario-based characteristics are very obvious, because they are generated to deal with specific problems in specific scenarios, such as the service alarm mechanism</p></li><li><p>Refine the key points to deal with the scenario</p><p>Distill the key aspects of responding to that scenario from you and experienced people, so the distillation of these key points will be much easier if there are successful experiences.<br />It is not recommended to organize a detailed operational documentation, and a step-by-step complete documentation is more important than the key point refinement, which will make the implementation costs lower, but also more operational.</p></li><li><p>Identify the supervisor</p><p>That is, who will ensure that the mechanisms are implemented, and at what point will the key points be checked, and how well each process and mechanism is implemented, and who will check and confirm</p></li><li><p>Evaluate operating costs</p><p>Confirm that the mechanism is operational for the implementer, that it was created to simplify the work, and ideally to achieve “autopilot” for management, and that if the creation of the mechanism results in higher operational costs for the implementer, it is necessary to reflect on the rationality of the mechanism</p></li><li><p>Consensus Building</p><p>Communicate and get consensus with relevant executors</p></li></ul></li><li><p>Principles of process mechanism establishment</p><ul><li><p>Operability</p><p>That is, the principle of simplicity, that is, the mechanism should be based on the principle of the lowest learning and operating costs, which is the most important principle, if the mechanism established does not have operability, then even if the managers feel perfect in themselves, the more problems they can cope with and solve, they should also be decisively abandoned</p></li><li><p>Hit only the key points</p><p>To establish the process mechanism, it is not necessary to describe all the details in full, no one likes long words, especially technical people, you just need to tell everyone what to do in those few key points</p></li><li><p>Clearly defined to the person</p><p>Principle of accountability. The question of who will follow up on each key point should be clearly agreed upon, and cannot rely entirely on human consciousness</p></li><li><p>Practical principles, to upgrade with the scene change</p><p>Come from work and go to work. Never create a mechanism for the sake of creating a mechanism; every mechanism must have practical value.<br />Since mechanisms are scenario-specific, when the scenario changes, the mechanism has to be upgraded as well. Revisiting and learning the mechanism means extra overhead, so each mechanism has a cost to maintain, and if it is not upgraded and updated as the scenario changes, it will become a meaningless mechanism, and over time it will become common: whatever mechanism is available, but the execution is not good</p></li></ul></li><li><p>Frequently Asked Questions about Process Mechanisms</p><ul><li><p>Is the more mechanisms the better</p><p>The mechanism is not more the better, but the less the better. This and the mechanism of the principle of simplicity, practical principle of the same line. The establishment of the mechanism does not solve the problem, the implementation of the mechanism to solve the problem, and the establishment of the mechanism, the implementation and post-maintenance are costly, so do not greedy more</p></li><li><p>People are reliable or mechanism is reliable</p><p>Human performance is more volatile, the point of the mechanism is to go to the lower limit of ensuring things when people are not reliable</p></li><li><p>The mechanism is reliable enough, is it not necessary to motivate</p><p>Mechanisms are a lower limit to ensure things are done, and are not a substitute for incentives</p></li></ul></li></ul></li><li><p>How to execute efficiently</p><p>A company owner once said that a competitor’s team was 996 every day, so he wanted his team to be 996 as well.<br />The question is, what does he hope to accomplish with 996.<br />He actually did not know why he wanted 996, just wanted everyone to work hard, as for what purpose to achieve, he was not clear.<br />Remember, 996 is only a means, and the means must serve an end, and when the end is not clear, the effectiveness of the means can not be judged. We often rely on the so-called “taken for granted” to make decisions, often fail to achieve the desired effect, and even contrary to expectations, the only effect is the stage of comfort</p><ul><li><p>Efficient execution = individual capacity * cooperative effectiveness * directional effectiveness * working hours</p><p>Many managers have put the focus on the length of work, which is a general incompetence, tired of the three armies</p><ul><li><p>Individual capacity = strength * willingness = capacity development * employee motivation</p></li><li><p>Cooperation effectiveness</p><p>Through the division of labor so that everyone can work together in one place, while relying on the trust and tacit understanding accumulated in general to make the team have a good level of collaboration</p></li><li><p>Directional validity</p><ul><li><p>The problem of talking about implementation in isolation from the goal</p><ul><li><p>Incentive failure</p><ul><li>Work repeatedly switched, the previous discussion evaluation design development have become a sunk cost</li><li>Time is getting tighter and the challenge is getting bigger</li><li>Employees think management is not thinking clearly and question management’s ability</li></ul></li><li><p>Collaboration disorders</p><ul><li>Clear and cognitively consistent goals help maintain a unified work pace</li><li>Lack of clarity in goals can lead to inefficient communication</li></ul></li><li><p>Busy and ineffective</p><ul><li>Clearly defined objectives</li><li>Define the metrics of the goal</li></ul></li></ul></li></ul></li></ul></li></ul></li></ul>]]></content>
    
    
    <summary type="html">From work, to work. Never build a mechanism for the sake of building a mechanism, every mechanism should have practical value. Since mechanisms are scenario specific, when the scenario changes, the mechanism has to be upgraded as well. Therefore, each mechanism has a cost to maintain. If it is not upgraded and updated as the scenario changes, it will become a meaningless mechanism, and over time it will become common，any mechanism is available, but the implementation is not good</summary>
    
    
    
    <category term="Sundry" scheme="https://sunra.top/en/categories/Sundry/"/>
    
    
  </entry>
  
  <entry>
    <title>Management Methodology of Technical Personnel (5) - Team Building Part 2</title>
    <link href="https://sunra.top/en/posts/3350143e/"/>
    <id>https://sunra.top/en/posts/3350143e/</id>
    <published>2023-06-07T12:52:08.000Z</published>
    <updated>2026-06-13T06:03:37.130Z</updated>
    
    <content type="html"><![CDATA[<ul><li><p>Echelon</p><p>The combination of the four elements of ability, motivation, division of labor, and cooperation can achieve a strong output of individual combat effectiveness and team combat effectiveness, but it cannot guarantee that the team has continuous motivation.<br />To improve the endurance and resilience of a team, two elements can be used to do the work, echelon training and team culture.<br />The echelon of a team, like the skeleton of the team, determines whether the team is robust; and the team culture is like the temperament and tone of the team, which will attract people with similar taste to continue to join and screen out people who do not meet the team temperament.</p></li></ul><span id="more"></span><pre><code>- Echelon planning- Echelon training- Selection and selection of training objects- PrincipleMaintain consistency in talent selection and team building- Ability: Whether the individual's ability matches the business characteristics, and whether its ability potential can be cultivated- Collaboration: their awareness and ability to collaborate, and whether they match the team's requirements and expectations- Culture: Its behavioral style and values, and whether they match the team's cultural values- Value people who complement each other  People with similar styles collaborate more effectively, but lack richer insights and perspectives.  - Cultivate the people you find- Align expectations  Managers and employees agree on the expectations of the employee's personal development. A common way is IDP, or personal development plan.  - No commitment principle: that is, do not promise any benefits to employees  On the one hand, being able to become the core backbone of the team depends on one's influence, not commitment. Second, if you can't deliver, this person may be lost.    PS: You don't promise any benefits, why should he listen to you? This person may be lost now  - do a good job of authorization  Ability and influence are accumulated in actual combat, which requires training objects to provide space and opportunities to do things.  - In advance- Examine the original intention  Be clear about what you want to gain in this authorization, whether you want to do something or bring people out  - Clear expectations  Let the training target clarify the expectations of managers  - Listen to his train of thought  After giving a good account of the authorized task, listen to his views and ideas on this matter first, and you can generally judge that the reason why he is independently responsible for this work is not reliable, and it is also a good recipe for risk control  - Important agreement  Managers should make an agreement on the things they are particularly concerned about and the training objects, such as how to check whether it is completed and when to check  - In progress- Check the progress- Give support- After the fact- evaluation results  For any authorization, give reasonable and well-founded evaluation and timely feedback on the work results and performance of the authorized object  - Insight advantage  What are the outstanding advantages of authorized objects in the entire authorization process?  - Positive feedback  Give some positive feedback on the work of the authorized object  - An improvement  Give one or two suggestions for improvement  - Build feedback- Establish a periodic communication mechanism to make communication routine- Review IDP, evaluation and feedback on the implementation of IDP, in order to reflect the greater value of IDP- Arrange a second mentor</code></pre><ul><li><p>Culture</p><p>What is team culture?</p><pre><code>There is no single clear definition of team culture itself, and every team has some conventional ways of working and judging right and wrong, so that in a team, even if no one tells you what is right and wrong, you are in general It can be clear what to do and what not to do.</code></pre><p>The value of team culture</p><pre><code>A clear team culture will bring at least four values to the team: efficiency, space, belonging and endurance  - Efficiency is the effect brought about by the orderliness of culture    Because the team culture contains conventional work standards and decision-making basis, and team members have consensus on this, there is no need to consult the superior for everything. A team that emphasizes &quot;safety&quot;, everyone will consider safety measures at work, and a unified code of conduct and tacit understanding of collaboration will greatly improve efficiency      - Space is the result of cultural orientation    In line with the premise of Value Proposition, employees can choose their own work methods, and even work content, which is a lot of initiative by the staff to provide independent play space      - Belonging is the effect of cultural screening    Team culture acts as a filter. People who agree with the culture will continue to join, while those who do not agree will gradually fade out      - Endurance is the result of cultural continuity    Culture is a relatively stable element for an organization. It can be passed on between new and old employees and will not change due to the changes of individual personnel</code></pre><ul><li><p>Steps to build team culture</p><ul><li><p>Refining</p><p>Put it in the right words</p><ul><li><p>Misunderstanding</p><p>The culture of your team has less to do with what culture you like and more to do with who you are</p><pre><code>  Facing problems and always complaining, then emphasizing a positive culture is not feasible  - In the face of cooperation, there is always confrontation, so emphasizing close cooperation is not feasible  - In the face of work, always wait passively, so it is not possible to advocate initiative  - In the face of subordinates, always indifferent, then emphasizing warmth is not enough</code></pre><ul><li><p>The more concise the better</p><ul><li>The purpose is for everyone to understand and remember, not the fewer words the better</li></ul></li></ul></li><li><p>Way</p><ul><li>Extract from your own excellent qualities, thereby amplifying the excellent qualities to the entire team. The qualities you do not have are not suitable for cultivation as a team culture</li></ul></li></ul></li><li><p>Advocate</p><p>Disseminate the refined culture to the entire team, including superiors and brother teams</p><ul><li>Not to talk to anyone, but to be aware of the team culture in some public or private occasions</li></ul></li><li><p>Practice</p><ul><li><p>Reasons why employees don’t buy into the culture</p><ul><li>When culture is refined, it is not extracted from the manager himself. The manager cannot lead by example, and his words and deeds are inconsistent</li><li>Did not combine team culture with management work, just talk without practice, did not let employees feel the benefits of practicing culture</li></ul></li></ul></li></ul></li></ul></li></ul>]]></content>
    
    
    <summary type="html">&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Echelon&lt;/p&gt;
&lt;p&gt;The combination of the four elements of ability, motivation, division of labor, and cooperation can achieve a strong output of individual combat effectiveness and team combat effectiveness, but it cannot guarantee that the team has continuous motivation.&lt;br /&gt;
To improve the endurance and resilience of a team, two elements can be used to do the work, echelon training and team culture.&lt;br /&gt;
The echelon of a team, like the skeleton of the team, determines whether the team is robust; and the team culture is like the temperament and tone of the team, which will attract people with similar taste to continue to join and screen out people who do not meet the team temperament.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="Sundry" scheme="https://sunra.top/en/categories/Sundry/"/>
    
    
  </entry>
  
  <entry>
    <title>Summary of the GAMES101 Series (5) - How Geometry is Expressed in Graphics</title>
    <link href="https://sunra.top/en/posts/43b8f2f/"/>
    <id>https://sunra.top/en/posts/43b8f2f/</id>
    <published>2023-06-03T23:35:35.000Z</published>
    <updated>2026-06-13T06:03:37.123Z</updated>
    
    <content type="html"><![CDATA[<p><a href="https://sunra.top/posts/83267170/">上一篇关于如何使用贴图的博客</a>中我们讲了如何从贴图中提取我们想要的数据。</p><p>In this blog, we will briefly talk about the application of maps, and then transition from displacement maps to the expression of aggregates.</p><h1 id="application-of-geometry"><a class="markdownIt-Anchor" href="#application-of-geometry"></a> Application of Geometry</h1><p>In GPU programming, the map is equal to the memory + range query in our CPU programming. We can use ByteGraph to paste the data we need in the calculation process and perform range queries on the data.</p><p>Therefore, the texture can not only be used to store the color information of the point on the object itself, but also can store information such as environment information, normal information, displacement information, etc.</p><span id="more"></span><h2 id="environmental-map"><a class="markdownIt-Anchor" href="#environmental-map"></a> Environmental map</h2><p>As shown in the figure below, the reflection of the environment on this teapot needs to be calculated in real time, but the environment is infinity, so the relative position of the teapot to the environment remains unchanged, and the reflection result is also unchanged, so we can calculate it in advance. Then save it in the map. When rendering, just mix the color map of the teapot itself and the sampling result of the environment map.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685836152/origin-of-ray/WX20230604-074845_2x_slesm0.png" alt="环境光贴图示例" /></p><h2 id="bump-map-normal-map"><a class="markdownIt-Anchor" href="#bump-map-normal-map"></a> Bump map (normal map)</h2><p>If our geometry itself is relatively smooth, we want to create a sense of unevenness on a smooth surface, such as creating a sense of asphalt road on a plane, we can use the way of bump mapping, because the so-called bump feeling we see is also caused by the different angles of light reflection. We can directly intervene through bump mapping when calculating the reflection angle.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685836608/origin-of-ray/WX20230604-075634_2x_punp7t.png" alt="凹凸贴图示例" /></p><h2 id="displacement-mapping"><a class="markdownIt-Anchor" href="#displacement-mapping"></a> Displacement mapping</h2><p>Just now we said that we can change the reflection angle of each point on the smooth surface by means of bump mapping to create a bump feeling. Then we can actually change the position of the point directly through displacement mapping when rendering. Rendering effect.</p><p>The difference between this method and bump mapping is that bump mapping does not change the position of the point, but only changes the direction of the normal, while the only mapping is to directly change the position of the point, which stores the position of the corresponding point based on the original position.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685836839/origin-of-ray/WX20230604-080024_2x_zs2mii.png" alt="位移贴图" /></p><p>So here is a question involved, I changed the position, how to calculate the new normal?</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685837204/origin-of-ray/WX20230604-080630_2x_hlz5v6.png" alt="" /></p><blockquote><p>The displacement map here is actually a representation of geometry, an explicit representation</p></blockquote><h1 id="representation-of-geometry"><a class="markdownIt-Anchor" href="#representation-of-geometry"></a> Representation of geometry</h1><p>There are many different ways of representing geometry, but there are mainly two, one is explicit and the other is implicit.</p><h2 id="implicit-representation"><a class="markdownIt-Anchor" href="#implicit-representation"></a> Implicit representation</h2><p>The so-called implicit way, which represents the relationship satisfied by the points on the set, theoretically we can get this geometry by finding all the points that satisfy the relationship.</p><p>Common implicit representations are:</p><ul><li>algebraic surface</li><li>level sets</li><li>distance functions</li></ul><h3 id="algebraic"><a class="markdownIt-Anchor" href="#algebraic"></a> algebraic</h3><p>For the implicit representation, it represents the relationship satisfied by the points on the set, so it can be very simple to determine whether a point is on the surface of the geometry, and its disadvantage is that it is difficult for you to see what it represents, as shown below</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685871570/origin-of-ray/WX20230604-173434_2x_xq4b0x.png" alt="" /></p><p>** Here we may have a question, that is, can this way of doing things only represent relatively simple and regular graphics? **</p><p>In fact, implicit way can represent very complex graphics, here to provide two ideas:</p><p>The first idea is that if we have studied advanced mathematics, any function can be Fourier expanded in the way that multiple functions are added together. Similarly, we can add enough functions to fit any function, as long as you have this knowledge reserve and willing to spend time.</p><p>The second idea is more like the idea we have when we make charts, using multiple simple graph splicing or elimination methods (that is, Boolean operations) to do it, as shown in the following figure:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685873239/origin-of-ray/WX20230604-180548_2x_rkvbsv.png" alt="" /></p><h3 id="distance"><a class="markdownIt-Anchor" href="#distance"></a> distance</h3><p>As shown in the figure, this method is a variant of the boolean operation of the second idea we just mentioned</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685873316/origin-of-ray/WX20230604-180825_2x_dqnxqs.png" alt="" /></p><p>Signed Distance Function (SDF) is a mathematical representation commonly used in Computer Graphics and geometric processing. It is used to describe the shortest distance from a point to the surface of a shape, and also contains the position information of the point relative to the surface of the shape. The value of SDF can be positive, negative or zero:</p><ol><li>When the point is located on the surface of the shape, the value of SDF is zero.</li><li>When the point is located inside the shape, the value of SDF is negative, indicating the shortest distance from the point to the surface of the shape.</li><li>When the point is located outside the shape, the value of SDF is positive, indicating the shortest distance from the point to the surface of the shape.</li></ol><p>SDF is widely used in many applications, such as ray tracing, collision detection, fluid simulation, etc. Its advantage is that it can efficiently calculate the distance between points and shapes, while retaining the position information of points relative to shapes.</p><p>In the above figure, in the process of merging two balls, we first calculate the distance function of any point in space relative to the surfaces of the two spheres, and then weigh it, leaving the point with 0 as the result</p><p>If the three-dimensional one is more difficult to understand, we can use a two-dimensional diagram to see:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685874029/origin-of-ray/WX20230604-181955_2x_bwc80b.png" alt="" /></p><h3 id="level"><a class="markdownIt-Anchor" href="#level"></a> level</h3><p>This method is also a variant. For the case where we cannot write an SDF, but can only write a rough table map, how do we get the result after fusion? Take a line as an example:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685874317/origin-of-ray/WX20230604-182337_2x_galu1n.png" alt="" /></p><h2 id="explicit-representation"><a class="markdownIt-Anchor" href="#explicit-representation"></a> Explicit representation</h2><p>The explicit representation is to directly give information to the out-point surface, or through parameter mapping, such as our very common Mesh. The displacement map we just mentioned is actually a mapping method, so we just said it is an explicit geometry representation.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685872152/origin-of-ray/WX20230604-174903_2x_ycsu26.png" alt="" /></p><p>Common explicit representations are:</p><ul><li>point cloud: point cloud</li><li>polygon mesh: we common mesh</li><li>Subdivision, simplification, regularization: subdivision, simplification, regularization</li></ul><p>The disadvantage of explicit representation is that it is more difficult to determine whether a point is on the surface of the geometry. As shown in the figure below:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685872127/origin-of-ray/WX20230604-174830_2x_tblcod.png" alt="" /></p><h3 id="point-cloud"><a class="markdownIt-Anchor" href="#point-cloud"></a> Point cloud</h3><p>This is easier to understand, is a large number of points, these points do not need to connect, as long as enough, you can not see the gap.</p><p>Because it is a series of points, it is good to store it in an array, but the amount of data is very large</p><h3 id="polygon-mesh"><a class="markdownIt-Anchor" href="#polygon-mesh"></a> Polygon mesh</h3><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685875059/origin-of-ray/WX20230604-183728_2x_umqfyz.png" alt="" /></p><h1 id="specific-usage-scenarios"><a class="markdownIt-Anchor" href="#specific-usage-scenarios"></a> Specific usage scenarios</h1><h2 id="bezier-curve"><a class="markdownIt-Anchor" href="#bezier-curve"></a> Bezier curve</h2><p>A Bezier curve is a method of determining a curve from several points. It has very common applications. For example, if we use xmind, when we establish a connection between different labels, it will give us four points, of which two The fixed point is the position of the two labels that need to be connected, and the other two points are given to us to drag, and after dragging, we can change the shape of the curve. This curve is a cubic Bezier curve.</p><p>Bézier curve can have n times (n is greater than or equal to 2), we take quadratic Bézier curve as an example to explain, and so on</p><p>As shown in the figure, suppose we have three points. Our three points determine that our curve starts at $b_0 $and ends at $b_1 $. The tangent direction of the starting point needs to be $\ vec {b_0b_1} $, and the tangent direction of the end point needs to be $\ vec {b_1b_2} $</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685875421/origin-of-ray/WX20230604-184317_2x_s9t7pt.png" alt="" /></p><p>Suppose we have a point that moves from $b_0 $to $b_1 $in time, then at any point t, its position should be:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685875422/origin-of-ray/WX20230604-184327_2x_zwtft8.png" alt="" /></p><p>The ratio of $b_0b_0 ^ 1 $to $b_0 ^ 1b_1 $, the ratio of $b_1b_1 ^ 1 $to $b_1 ^ 1b_2 $, the ratio of $b_0 ^ 1b_0 ^ 2 $to $b_0 ^ 2b_1 ^ 1 $are all t/(1-t)</p><p>Quadratic Bézier curve is actually to use three points to get two new points proportionally, and then to get a point proportionally on the connection of the new two points</p><p>The cubic Bézier curve is actually four points that determine the curve, and the way it connects gradually becomes one point from four points</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685876629/origin-of-ray/WX20230604-190230_2x_jvrfhj.png" alt="" /></p><p>The higher Bezier curve is actually the recursion of the above process:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685876770/origin-of-ray/WX20230604-190558_2x_ka27xu.png" alt="" /></p><p>We just talked about how the Bézier curve is obtained, so how to express this process in a formula? The following is the result of the quadratic Bézier curve</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685876959/origin-of-ray/WX20230604-190907_2x_p480q9.png" alt="" /></p><p>The result is that we actually take the coefficients on the right side of the equation and it’s the expansion of $ (1 - t + t) ^ 2 $</p><p>For a higher-order Bézier curve, the formula is as follows, where B represents the expansion of the binomial distribution, that is, the probability of getting a result each time is t, then the probability of j results in n independent replicates:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685877128/origin-of-ray/WX20230604-191159_2x_ydqw3a.png" alt="" /></p><h3 id="joining-of-bézier-curves"><a class="markdownIt-Anchor" href="#joining-of-bézier-curves"></a> Joining of Bézier curves</h3><p>When our curve is a very high-order Bézier curve, it is actually difficult to control, as shown in the figure below:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685877394/origin-of-ray/WX20230604-191433_2x_nhew7z.png" alt="" /></p><p>So we can take the method of splicing multiple low-order Bézier curves:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685877395/origin-of-ray/WX20230604-191622_2x_mejshx.png" alt="" /></p><h2 id="bessel-surface"><a class="markdownIt-Anchor" href="#bessel-surface"></a> Bessel surface</h2><p>A Bézier surface is a surface controlled by 4 * 4 = 16 points:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685877530/origin-of-ray/WX20230604-191801_2x_fdb6aw.png" alt="" /></p><p>As shown in the figure below, first of all, we can get a Bézier curve from the four points of each line horizontally. At this time, we get four Bézier curves, and then we imagine that there is a plane cut vertically, and four Bézier curves get four points, these four points can then determine a Bézier curve, and we can get a Bézier surface in the process of moving this numerical surface:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685877530/origin-of-ray/WX20230604-191809_2x_aojora.png" alt="" /></p><p>This process is actually a recursion process.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685877822/origin-of-ray/WX20230604-192243_2x_rri2kz.png" alt="" /></p><h2 id="mesh"><a class="markdownIt-Anchor" href="#mesh"></a> Mesh</h2><p>The so-called mesh subdivision refers to splitting the polygons in the mesh to obtain a smoother effect</p><p>From the definition, we can see that this mesh subdivision actually has two things to do. The first thing is to split the polygon, and the second part is to adjust the split polygon, otherwise the simple split will not be The smoother effect will be obtained, for example, we connect the midpoints of the three sides of a triangle to obtain four triangles, but these four triangles are still on one surface, and there will be no smoother effect</p><h3 id="loop"><a class="markdownIt-Anchor" href="#loop"></a> Loop</h3><blockquote><p>It’s called Loop only because the person who invented the algorithm is called Loop.</p></blockquote><p>The first step of the algorithm is to connect the vertices of the three sides of the triangle, and we have four triangles.</p><p>Next we need to update the position of the dots to make the split face smoother:</p><p>For the three new points, we update the coordinates in the following way</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685878264/origin-of-ray/WX20230604-193041_2x_atmqd9.png" alt="" /></p><p>For the original three points, we update as follows:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685878264/origin-of-ray/WX20230604-193048_2x_zjmgjl.png" alt="" /></p><h3 id="catmull-clark"><a class="markdownIt-Anchor" href="#catmull-clark"></a> Catmull-Clark</h3><p>The limitation of Loop subdivision is obvious, it can only split triangles, so how do we split polygons?</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685878453/origin-of-ray/WX20230604-193338_2x_jacoyn.png" alt="" /></p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685878491/origin-of-ray/WX20230604-193440_2x_m28frs.png" alt="" /></p><p>It can be seen that only the first split will increase the number of singularities, that is, only the first time the triangle is split into three quadrilaterals, how to split the quadrilateral is a quadrilateral.</p><p>So how do we use the updated position of the new quadrilateral?</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685878677/origin-of-ray/WX20230604-193716_2x_ypkihf.png" alt="" /></p><h2 id="mesh-2"><a class="markdownIt-Anchor" href="#mesh-2"></a> Mesh</h2><h3 id="edge-collapse"><a class="markdownIt-Anchor" href="#edge-collapse"></a> Edge collapse</h3><p>In fact, one edge is deleted, or the two vertices of the edge are merged into one.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685878849/origin-of-ray/WX20230604-194001_2x_afzlfm.png" alt="" />、</p><p>This scheme sounds simple, but there are two problems, which side to remove, and where the position of the merged point can introduce the smallest error.</p><blockquote><p>Note that in graphics, many of the so-called most only mean acceptable effects</p></blockquote><p>Here we introduce a new concept called quadratic metric error, that is, the distance from the plane L2 where the distance is deleted and the minimum L2 distance</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685879253/origin-of-ray/WX20230604-194447_2x_eou8un.png" alt="" /></p><p>We only need to calculate the quadratic measurement error of all faces, and then select the smallest deletion in turn.</p><p>There is actually a problem here, that is, after each deletion, it will affect the position of some points, thus affecting their secondary measurement error. We need to recalculate and reorder to get the smallest one for deletion. Here we need to use the priority queue data structure, get the team head for deletion every time, then update the affected secondary measurement error, and then get it from the team head.</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;a href=&quot;https://sunra.top/posts/83267170/&quot;&gt;上一篇关于如何使用贴图的博客&lt;/a&gt;中我们讲了如何从贴图中提取我们想要的数据。&lt;/p&gt;
&lt;p&gt;In this blog, we will briefly talk about the application of maps, and then transition from displacement maps to the expression of aggregates.&lt;/p&gt;
&lt;h1 id=&quot;application-of-geometry&quot;&gt;&lt;a class=&quot;markdownIt-Anchor&quot; href=&quot;#application-of-geometry&quot;&gt;&lt;/a&gt; Application of Geometry&lt;/h1&gt;
&lt;p&gt;In GPU programming, the map is equal to the memory + range query in our CPU programming. We can use ByteGraph to paste the data we need in the calculation process and perform range queries on the data.&lt;/p&gt;
&lt;p&gt;Therefore, the texture can not only be used to store the color information of the point on the object itself, but also can store information such as environment information, normal information, displacement information, etc.&lt;/p&gt;</summary>
    
    
    
    <category term="Unity" scheme="https://sunra.top/en/categories/Unity/"/>
    
    
  </entry>
  
  <entry>
    <title>Summary of the GAMES101 Series (4) - How to Apply Texture Mapping</title>
    <link href="https://sunra.top/en/posts/83267170/"/>
    <id>https://sunra.top/en/posts/83267170/</id>
    <published>2023-05-25T10:43:16.000Z</published>
    <updated>2026-06-13T06:03:37.123Z</updated>
    
    <content type="html"><![CDATA[<p><a href="https://sunra.top/posts/2a17dbd0/">上一篇关于Shading的博客</a>中最后我们提到了Texture是我们用来对点进行输入的方式。</p><p>Before we said, each point has its own UV coordinates, and then find the corresponding point on the map through the UV coordinates, and then take out the value. We can interpolate the pixels in the middle of the triangle through the center coordinates.</p><p>But the problem is, if our map is too small, it may cause the model to have multiple points corresponding to the same UV, which will cause blurring. On the contrary, if the map is too large and the UV coordinate difference is too large, it will cause the final jagged or moiré effect.</p><p>This article will talk about how game engines solve these two problems.</p><span id="more"></span><h1 id="basic-sampling-rules"><a class="markdownIt-Anchor" href="#basic-sampling-rules"></a> Basic sampling rules</h1><p>(X, y) are the pixel coordinates on the screen, (u, v) are the texture coordinates corresponding to the points on the model</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">for each rasterized screen sample (x,y): </span><br><span class="line">    (u,v) = evaluate texture coordinate at (x,y) </span><br><span class="line">    texcolor = texture.sample(u,v);</span><br><span class="line">    set sample’s color to texcolor;</span><br></pre></td></tr></table></figure><h1 id="what-happens-if-the-sticker-is-too-small"><a class="markdownIt-Anchor" href="#what-happens-if-the-sticker-is-too-small"></a> What happens if the sticker is too small</h1><h2 id="solution-1-texture-enlargement"><a class="markdownIt-Anchor" href="#solution-1-texture-enlargement"></a> Solution 1: Texture enlargement</h2><p>This scheme is the simplest scheme, the texture is too small to be enlarged by a certain algorithm.</p><p>Here we introduce a new concept called texel, which is a pixel on a texture, and our UV coordinates take a texel from the texture</p><p>There are three common algorithms for texture amplification: Nearest, Biliner, Bicubic</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685012251/origin-of-ray/WX20230525-185641_2x_ngjuhb.png" alt="三种算法纹理放大效果图" /></p><p>Let’s take Biliner as an example to explain the process of texture enlargement.</p><p>Suppose we want to sample the value of the red point in the following figure, we select four points around the point, then calculate the distance between the point we want to sample and the center of the four texels, and interpolate with this distance:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685012555/origin-of-ray/WX20230525-190006_2x_uxgax3.png" alt="Biliner插值过程" /></p><h1 id="what-happens-if-the-texture-is-too-large"><a class="markdownIt-Anchor" href="#what-happens-if-the-texture-is-too-large"></a> What happens if the texture is too large</h1><p>First, let’s look at a rendering:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685012653/origin-of-ray/WX20230525-190358_2x_eujo53.png" alt="" /></p><p>In the near place, because the texture is too large, some details are lost, resulting in jagged teeth, while in the distance, molar patterns are produced due to too many details. (The reason belongs to personal understanding, but the effect is right)</p><p>When the texture is too large, it actually has the following effect:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685065463/origin-of-ray/WX20230526-094407_2x_irakss.png" alt="" /></p><p>That is, when we use the “basic sampling rule” mentioned at the beginning to find a certain textured element on the map, we find not one, but a piece.</p><blockquote><p>In other words, if the texture is too small, multiple pixels will find the same texel, and if the texture is too large, one pixel can match multiple texels</p></blockquote><h2 id="option-1-supersampling"><a class="markdownIt-Anchor" href="#option-1-supersampling"></a> Option 1: Supersampling</h2><p>The algorithm of this oversampling technique is actually the same as the texture amplification just now, but for the case of too small a texture, oversampling is aimed at the original map, which is used to generate a higher resolution original map, and when the map is too large, A pixel may correspond to multiple texels, so the sampling result of the pixel from the map is jointly determined by multiple texels around it.</p><p>The following picture shows the effect of super sampling:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685066672/origin-of-ray/WX20230526-100416_2x_gbp78o.png" alt="" /></p><p>It can be seen that supersampling is indeed effective, but the problem is that the calculation cost is too high, and each pixel needs to calculate the value of multiple points and interpolate.</p><h2 id="option-2-find-the-average"><a class="markdownIt-Anchor" href="#option-2-find-the-average"></a> Option 2: Find the average</h2><p>Supersampling calculation is troublesome, we can simply average it over a range</p><h2 id="option-3-mipmap"><a class="markdownIt-Anchor" href="#option-3-mipmap"></a> Option 3: Mipmap</h2><p>This is a faster range query, is a kind of space for time idea, we need to calculate the results of the range query at different sampling frequencies in advance and store them in the map, that is, to generate maps with different degrees of low resolution. When the map is too large, go directly to the smaller resolution map to find it.</p><p>Mipmap is a texture mapping technique used to render textures with different details at different distances and angles. A Mipmap texture is composed of multiple texture images of different resolutions, each image is 1/4 the size of the previous image. The level of Mipmap refers to the first few images in the Mipmap texture, counting from 0, and 0 is the original texture image.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685067134/origin-of-ray/WX20230526-101158_2x_od1rbi.png" alt="" /></p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685067194/origin-of-ray/WX20230526-101305_2x_rznotd.png" alt="" /></p><p>This plan has two key points:</p><ol><li>Generate different levels of Mipmap</li><li>How to determine which level of Mipmap to use</li></ol><p>The first point is the image compression algorithm, there are many, we do not go into detail, nor rendering specific knowledge, we mainly look at how to determine the level, that is, the “D”</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685067404/origin-of-ray/WX20230526-101635_2x_mhbe63.png" alt="" /></p><p>The level of Mipmap can be calculated using the following formula:</p><p>level = log2(max(w, h))</p><p>Where w and h are the width and height of the texture image, and max (w, h) represents the maximum value in width and height. This formula means that each Mipmap level image is 1/4 the size of the previous level image, so use the logarithm function to take 2 as the base when calculating, and you can get the size of the largest level.</p><p>For example, if the size of the original texture image is 512x512 pixels, the Mipmap texture contains 8 levels, which are level 0 to 7. Level 0 is the original image, level 1 is a 256x256 pixel image, level 2 is a 128x128 pixel image, and so on.</p><p>We need to use a reasonable Level to have a good price comparison effect. The higher the level, the less details. If we use the oversampling method with too little texture, it will be more blurry:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685067916/origin-of-ray/WX20230526-102501_2x_ihkpzv.png" alt="" /></p><h2 id="plan-4-anisotropic"><a class="markdownIt-Anchor" href="#plan-4-anisotropic"></a> Plan 4: Anisotropic</h2><p>Mipmap actually has limitations, it can only do mipmap on textures in the positive direction.</p><p>Because of his limitation, on the one hand, when sampling, many unused points will be used, increasing the amount of calculation, and secondly, some pixels correspond to rectangles covering multiple texels, resulting in oversampling blur.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685068320/origin-of-ray/WX20230526-103146_2x_veggr4.png" alt="" /></p><p>For the case of rectangles, we can use Anisotropic Filtering</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1685068399/origin-of-ray/WX20230526-103312_2x_hr9ugc.png" alt="" /></p><p>Scaled square maps are on the diagonal, other locations store some width compressed and length compressed maps</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;a href=&quot;https://sunra.top/posts/2a17dbd0/&quot;&gt;上一篇关于Shading的博客&lt;/a&gt;中最后我们提到了Texture是我们用来对点进行输入的方式。&lt;/p&gt;
&lt;p&gt;Before we said, each point has its own UV coordinates, and then find the corresponding point on the map through the UV coordinates, and then take out the value. We can interpolate the pixels in the middle of the triangle through the center coordinates.&lt;/p&gt;
&lt;p&gt;But the problem is, if our map is too small, it may cause the model to have multiple points corresponding to the same UV, which will cause blurring. On the contrary, if the map is too large and the UV coordinate difference is too large, it will cause the final jagged or moiré effect.&lt;/p&gt;
&lt;p&gt;This article will talk about how game engines solve these two problems.&lt;/p&gt;</summary>
    
    
    
    <category term="Unity" scheme="https://sunra.top/en/categories/Unity/"/>
    
    
  </entry>
  
  <entry>
    <title>Management Methodology of Technical Personnel (4) - Team Building Part 1</title>
    <link href="https://sunra.top/en/posts/409cc99/"/>
    <id>https://sunra.top/en/posts/409cc99/</id>
    <published>2023-05-21T01:43:25.000Z</published>
    <updated>2026-06-13T06:03:37.129Z</updated>
    
    <content type="html"><![CDATA[<h3 id="what-makes-a-good-team"><a class="markdownIt-Anchor" href="#what-makes-a-good-team"></a> What makes a good team?</h3><ul><li><p>Good performance</p><ul><li>Direction: Manage the planning phase, define what constitutes good performance, and plan the team to match it</li><li>Lead people: that is, the team building stage, continuously improve the team’s ability to achieve performance, including individual ability and team ability</li><li>Work: task management stage, how to implement the plan through good control and produce results</li></ul></li><li><p>High efficiency</p><ul><li>Look at the direction: the clearer the goal, the higher the efficiency</li><li>Lead people: The stronger the individual ability of team members, the higher the level of cooperation among team members, and the higher the team efficiency</li><li>Work: The more efficient the processes and rules, the more skilled the operation, the higher the efficiency of work</li></ul></li><li><p>Sustainable</p><ul><li>Look at the direction: the rationality and effectiveness of team planning</li><li>Lead people: perfect layers and mature team culture</li><li>Work: The tenacity of the team is honed, and honed cannot be separated from continuous work</li></ul></li></ul><span id="more"></span><h3 id="team-building-elements"><a class="markdownIt-Anchor" href="#team-building-elements"></a> Team building elements</h3><h4 id="capacity"><a class="markdownIt-Anchor" href="#capacity"></a> Capacity</h4><ul><li><p>Components of capacity</p><ul><li><p>Capability three core</p><ul><li><p>Knowledge</p><p>Knowledge and understanding of information, generally measured in breadth and depth</p></li><li><p>Skills</p><p>The skill and ability to perform and perform a job, generally measured by proficiency</p></li><li><p>Talent</p><ul><li>Spontaneous high-frequency patterns of thought, action, and feeling, including character traits, etc</li></ul></li></ul></li><li><p>Three dimensions of work ability</p><ul><li><p>Professional competence</p><ul><li><p>For technical people, it generally refers to technical ability, which is different for different teams. Can be measured in breadth and depth</p><p>Breadth: Represents how large-scale things can be done<br />Depth: Represents how complex things can be done</p></li></ul></li><li><p>General ability</p><p>Such as: structured thinking ability. Teamwork ability. Project management ability. Quick learning ability</p></li><li><p>Personality strength</p><p>Personality strength usually refers to a person’s stable attitude and performance in the face of a certain situation, such as facing difficulties, perseverance, and positivity.<br />These personality forces are sometimes crucial to the ability to get something done, but they are not cultivated overnight. They often come from everyone’s long-term life and work experience, and once formed, they are difficult to change.<br />But hard to change doesn’t mean it can’t be changed. In order for team members to tend to a certain common temperament, managers need to unequivocally advocate the character that the team promotes.</p></li></ul></li></ul></li><li><p>Objectives of capacity building</p><p>It is best to focus on learning goals, rather than scattered knowledge points</p><ul><li><p>For example</p><ul><li><p>Professional competence perspective</p><p>Prior Art Series<br />Core technology thematic learning:<br />Architecture topics<br />Storage topics<br />Front-end topics<br />Security topics<br />Operation and maintenance topics<br />Automated Testing Topics<br />Expand new technologies<br />New technologies needed for business development<br />Technology in the field</p></li><li><p>General ability perspective</p><p>Project management capabilities<br />The ability to bring people<br />Communication skills</p></li></ul></li></ul></li><li><p>Standards for capacity building</p><p>What is the original intention of improving employee capabilities? Different original intentions decide what standards to develop, and then write this standard into the employee’s personal development plan and agree with them</p><ul><li>Avoid unclear expectations leading to high expectations or poor results</li><li>Reasonably arrange the energy input of managers, and reasonably allocate the energy invested in different training objects</li></ul></li><li><p>Methods of capacity building</p><p>7% rely on work practice, 2% rely on mutual communication, and 1% rely on listening to lectures and reading books for self-study</p></li><li><p>Employee Willingness to Learn</p><p>How to stimulate the motivation and willingness of employees to learn?</p><ul><li><p>Push: give pressure, push him to learn</p><p>Provide clear job requirements</p><ul><li>Establish learning mechanisms. Such as mandatory compliance with learning rules and completion of learning tasks</li></ul></li><li><p>Pull: Give direction and guide him to learn</p><ul><li>Set an example</li><li>Equipped with tutors</li><li>Develop a skills map for the team to grow</li></ul></li><li><p>Let go: give room to play and learn independently</p><ul><li>Give employees the opportunity to shoulder heavy responsibilities<br />Give employees space to think independently</li><li>Give him confidence and patience, allow him to make mistakes and take detours</li></ul></li></ul></li><li><p>Two beliefs in ability development</p><ul><li><p>Believe in the diversity of employees’ abilities, that is, see the differences and value the richness</p><p>In the era of knowledge economy, the creativity of employees can bring greater value to the team, and creativity often comes from the collision of differences</p></li><li><p>Believe in the system of team capabilities, that is, appreciate differences and value complementarities</p></li></ul></li><li><p>Motivation</p><p>Individual combat effectiveness depends on two elements: individual ability and willingness to use ability</p><ul><li><p>The challenge of employee motivation</p><p>Upward communication, employee motivation and team cohesion are the three most challenging management themes in managers minds</p><ul><li><p>Incentive cognitive non-system</p><p>Understand some motivation skills and methods, but do not understand the overall picture of motivation, nor the reasons behind it, so there is no systematic incentive plan</p></li><li><p>Lack of incentives</p><p>Real material incentives are not controlled by managers, and the spirit of “painting a pie” motivates employees without buying it, so there are few incentives available</p></li><li><p>Incentives don’t get the point</p></li></ul></li></ul><p>Maslow’s Hierarchy of Needs</p><p>Does this theory apply to China? Is there anything that needs to be changed according to local conditions?</p><p>Three Stages of Employee Motivation Development</p><ul><li><p>Instinct</p><p>Mainly derived from the desire for survival and security, the hierarchy of needs is at the bottom of the “Maslow Hierarchy of Needs Model”.</p></li><li><p>Outside drive</p><p>The underlying philosophy is “seek reward, avoid punishment” - carrots and sticks - a widely accepted form of motivation in the industrial age for nearly 200 years. Its central purpose is to make employees “obey”.<br />At the same time, Taylor’s “scientific management theory” believed that workers were like parts in a machine, they just needed to do the right thing in the right way at the right time to ensure that the machine worked well. In the industrial age of assembly lines, workers were required to do “obedience” rather than ingenuity</p><ul><li><p>Existing problems</p><ul><li><p>For most managers, material incentives are beyond the control of managers except for the pie</p></li><li><p>Lead to the disappearance of intrinsic motivation and reduce employee self-motivation</p></li><li><p>Causing a decline in performance</p></li><li><p>Kill creativity</p></li><li><p>Suppress good deeds</p><p>For example, when a team’s rewards for excellence are not obvious, but the penalties for mistakes are severe</p></li><li><p>Encouraging fraud, shortcuts, unethical tactics</p></li><li><p>Addictive, making employees addicted to external incentives</p></li><li><p>Breeds short-sighted thinking</p></li><li><p>Will gradually be immune, “Those who are good at using authority will not be easily angry, and those who are good at using grace will not give indiscriminately”</p></li></ul></li><li><p>Non-material incentives</p><p>Such as praise and positive feedback, the negative harm of external incentives is low, and it is a commonly used external means</p><ul><li><p>Specific principle: the content of praise should be specific</p></li><li><p>Disclosure principle: public recognition</p><ul><li>Give praised employees more incentive</li><li>Tell everyone in the team what behaviors and values the team agrees with and advocates</li></ul></li><li><p>Timely principle</p></li></ul></li></ul></li><li><p>Inside drive</p><ul><li><p>Three aspects of internal drive</p><ul><li>Take control of your own life, i.e. “autonomy”</li><li>Extend your abilities, i.e. “specialization”</li><li>Make life more meaningful, i.e. “purpose”</li></ul></li><li><p>Using internal drive to motivate employees is an unavoidable choice</p><ul><li><p>Choice of times</p><p>In the era of knowledge economy, the creativity of employees can create more value for the company, and creativity requires autonomy and difference, which is almost the opposite of the concept of the industrial age.</p></li><li><p>People’s choice</p><p>With the development of China’s economy and culture, material rewards and punishments and the evaluation of others have become less important than before. Many professionals have their own unique work values, especially whether they are willing to do it</p></li></ul></li><li><p>How to excite</p><ul><li><p>Increases employee autonomy, that is, gives employees a certain degree of autonomy and control</p><ul><li><p>The first is the freedom to work when and where</p></li><li><p>Secondly, the degree of freedom of work content</p><p>Employees can choose their own work content to a certain extent</p></li></ul></li><li><p>Improve the precision of employees, so that employees continue to grow</p><p>Specialization here does not emphasize setting goals to become an expert, but emphasizes the process of self-involvement, creating conditions for employees to be willing to self-invest</p><ul><li><p>Clear work objectives</p><p>The clearer the requirements for the employee, the more willing he is to put in the effort</p></li><li><p>The goal should be slightly challenging</p><p>Demanding too much from employees can lead to anxiety, and too little can lead to boredom</p></li><li><p>To be able to use its advantages</p><p>Everyone is willing to do what they are good at, and if a job can give full play to the unique advantages of employees, employees will definitely be enthusiastic.<br />Advantages can have many levels, we may not be able to meet the work content expected by an employee, but we can also consider the behavior mode and thinking mode, such as letting it do some communication</p></li></ul></li><li><p>Improve the sense of meaning and mission of work</p><p>While not rejecting benefits, pursue maximizing “value” and hope that the work you do is meaningful and valuable<br />There is always a group of people who leave because their work is worthless. They are not hypocritical, but really need their work to be valuable</p></li></ul></li></ul></li><li><p>Employee happiness</p><p>Total Sustainable Well-being (PERMA)</p><p>Not just emotional happiness, but a flourishing state of life that Martin Seligman calls “blooming.”</p><ul><li><p>Positive emotions</p><p>What kind of team atmosphere are you creating? Are team members trusting each other, cooperating happily, helping each other or complaining and accusing each other?</p></li><li><p>Human relationships</p><p>What have you done to improve your employees’ sense of belonging and inclusion? Are there activities and mechanisms involved to make employees more willing to support each other, such as more commonly, have you assigned a designated mentor to each employee?</p></li><li><p>Put in</p><p>Whether the conditions are created for employee autonomy, such as setting clear goals, giving them appropriate challenges, and supporting them to play to their strengths</p></li><li><p>Achievement</p><p>Meeting challenges and achieving success is something that most engineers enjoy, but it requires a premise, which is our characterization of achievement.<br />Make daily work projects and milestone large-scale projects</p></li><li><p>Meaning of life</p></li></ul></li><li><p>Design of incentive schemes</p><ul><li><p>Incentives</p><p>Is the incentive plan aimed at an individual, a group or the entire team?</p></li><li><p>Incentive purposes</p><p>Clarify the effect that the incentive plan wants to achieve</p></li><li><p>Incentive type</p><p>Mainly to distinguish whether the plan focuses on short-term effects or long-term effects</p></li><li><p>Incentives</p><p>Choose what motivational elements to work on, each element of the three phases of the drive, all five elements of PERMA can be considered</p></li><li><p>The situation of the incentive object</p><p>To be motivated to have a sufficient understanding of the object, such as the object of the incentive base line is what, only significantly more than the base line has the incentive effect, if below the base line, there will be obvious negative incentive</p></li><li><p>Reasonableness assessment</p><ul><li>Consider the cost performance ratio from the cost<br />Risk: that is, who will create obvious negative incentives</li></ul></li><li><p>Incentive timing</p></li></ul></li><li><p>Responding to employee motivation challenges</p><ul><li>Cognition of motivation: upgrade from a single incentive dimension to a three-dimensional incentive system</li><li>Incentive efforts should be used in peacetime, rather than relying on some temporary stimulation programs</li><li>Understand the elements to consider when designing an incentive program and be able to operate</li></ul></li></ul></li></ul><h4 id="division-of-labor"><a class="markdownIt-Anchor" href="#division-of-labor"></a> Division of labor</h4><ul><li><p>The purpose of the division of labor</p><p>Many people’s first reaction is to improve efficiency. However, if efficiency is pursued, the division of labor should be reduced, because the more people cooperate, the lower the efficiency, so some teams’ performance will increase after layoffs.</p><p>In order to achieve scale, the division of labor is not for efficiency, but for scale</p><ul><li>Collaboration: Division of labor is the means, collaboration is the end</li><li>Achieve specialization</li></ul></li><li><p>Common organizational structure</p><ul><li><p>Matrix structure</p><p>Employees team up according to their roles and are divided into different role teams, each team has its own person in charge. When you want to do a project, there will be a special project manager to apply for manpower from each team leader.</p><ul><li>Pros: The professionalism of the team in each role is high</li><li>Disadvantage: The project is relatively inefficient to execute</li></ul></li><li><p>BU type structure</p><p>All personnel and resources for a business are deployed in a unified manner. No matter whether the business department is large or small, it has a full range of roles.</p><ul><li>Advantages: High cooperation efficiency</li><li>Disadvantage: Redundant resources</li></ul></li></ul></li><li><p>Common division of labor issues</p><ul><li><p>Blurred division of labor</p><p>This is the most common misunderstanding, and even some managers in order to let everyone complement each other, take the initiative to undertake, enhance mutual assistance, but also to blur the boundary, the so-called “de-boundary”.<br />However, it should be noted that any blurring of boundaries that is not premised on a clear division of labor will backfire. Because:<br />Only a clear division of labor can bring a sense of belonging and be willing to take the initiative to give more. As long as you understand what you should do, you can know what you do is “proactive”</p></li><li><p>Division of labor stability issues</p><p>Only stable division of labor can reflect the value of division of labor</p><ul><li>The continuous adjustment of the business will cause the division of labor to change constantly</li><li>Long-term stable division of labor, while bringing expertise, will also bring limitations and laziness, fragmented vision</li></ul></li></ul></li><li><p>Virtual organization</p><ul><li><p>Advantages</p><ul><li><p>Efficient execution</p><p>The organization of virtual teams is generally for dedicated people, focused goals, and efficient execution</p></li><li><p>Reasonable allocation of resources</p><p>For many tasks, it is not worthwhile to form a dedicated team, but from time to time new projects need to be set up. Virtual teams provide a solution for such needs. Everyone can come together to do things, but not as a team with an independent budget</p></li><li><p>Maintain a sense of belonging</p></li></ul></li><li><p>Principle</p><ul><li><p>Specialized people, not too many</p></li><li><p>Recognize employee value</p><p>Now that you have agreed to your employee’s participation in this virtual organization, you must recognize his value regardless of whether the performance is what you value most.<br />Many managers often depress employee performance on the grounds that employee output is not of great value to their team, which is a typical example of letting employees bear the consequences of managers’ decisions</p></li><li><p>Clear goals and responsibilities</p></li></ul></li></ul></li></ul><h4 id="collaboration"><a class="markdownIt-Anchor" href="#collaboration"></a> Collaboration</h4><p>The direction of effort is: tacit understanding like a person</p><p>How to improve the level of collaboration</p><pre><code>- Overall coordination  - Evaluate the level of collaboration and identify work priorities    For the level of collaboration, it is difficult for us to give a measure, but the level of collaboration is excellent and medium, which can be roughly felt.    Mainly to answer a question: what are the main problems in the current collaboration, and what can be done to significantly improve the level of collaboration  - Advocate and promote various tasks    Implement the concept of &quot;collaboration is important&quot; to team members, and promote some measures for employees to switch height to promote collaboration  - Overall coordination, provision of arbitration    Collaboration is a dynamic process. There will definitely be differences and frictions among employees in the process of collaboration. Managers should take resolving differences as an opportunity to improve collaborative relationships.    Resolving differences and contradictions in cooperation is precisely the most effective means to improve the level of cooperation- Establishment of mechanisms  Employees don't work well together just because they are proactive, and managers need to provide templates and guidance to avoid confusion and overwhelm.  How employees should collaborate is not naturally clear, and managers need to establish some mechanisms to guide everyone.  - Enhance mutual trust  - Deep and solid mutual understanding  - Targeted team building activities  - Increase opportunities for cooperation and face challenges together- Keep practicing</code></pre>]]></content>
    
    
    <summary type="html">&lt;h3 id=&quot;what-makes-a-good-team&quot;&gt;&lt;a class=&quot;markdownIt-Anchor&quot; href=&quot;#what-makes-a-good-team&quot;&gt;&lt;/a&gt; What makes a good team?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Good performance&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Direction: Manage the planning phase, define what constitutes good performance, and plan the team to match it&lt;/li&gt;
&lt;li&gt;Lead people: that is, the team building stage, continuously improve the team’s ability to achieve performance, including individual ability and team ability&lt;/li&gt;
&lt;li&gt;Work: task management stage, how to implement the plan through good control and produce results&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;High efficiency&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Look at the direction: the clearer the goal, the higher the efficiency&lt;/li&gt;
&lt;li&gt;Lead people: The stronger the individual ability of team members, the higher the level of cooperation among team members, and the higher the team efficiency&lt;/li&gt;
&lt;li&gt;Work: The more efficient the processes and rules, the more skilled the operation, the higher the efficiency of work&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sustainable&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Look at the direction: the rationality and effectiveness of team planning&lt;/li&gt;
&lt;li&gt;Lead people: perfect layers and mature team culture&lt;/li&gt;
&lt;li&gt;Work: The tenacity of the team is honed, and honed cannot be separated from continuous work&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="Sundry" scheme="https://sunra.top/en/categories/Sundry/"/>
    
    
  </entry>
  
  <entry>
    <title>Management Methodology of Technical Personnel (3) - Management Planning</title>
    <link href="https://sunra.top/en/posts/e0457b53/"/>
    <id>https://sunra.top/en/posts/e0457b53/</id>
    <published>2023-05-14T08:33:52.000Z</published>
    <updated>2026-06-13T06:03:37.129Z</updated>
    
    <content type="html"><![CDATA[<p>When it comes to management planning, most managers are no strangers, because managers need to do planning every six months or every quarter. Some companies call it formulating KPIs, some companies call sorting out team OKRs, and some companies call it quarterly planning or annual planning. In short, it is to agree with the superior what we will do next and how to evaluate whether we are doing well. For managers, this is the most important agreement to align with the superior.</p><p>To be precise, the setting of team KPIs and OKRs is only a part of management planning, because this only reflects the expectations of the superior to the team, and cannot fully cover all the planning of your management work as a team leader</p><span id="more"></span><h3 id="concept"><a class="markdownIt-Anchor" href="#concept"></a> Concept</h3><ul><li><p>Basic meaning</p><p>Construct your own management ideals in the mind of managers</p></li><li><p>Presentation form</p><p>Work agreement reached between managers and superiors to achieve good coordination between superiors and subordinates</p></li><li><p>Core content</p><p>Management planning requires managers to answer a clear question: “How do you plan to lead this team?”</p><ul><li><p>Answer the superior</p><p>The usual angle is to answer from two perspectives: input and output</p></li><li><p>Answer yourself</p><ul><li><p>Functions</p><p>What is the purpose of the superior setting up this team?</p></li><li><p>Target</p><p>What are the expectations of the superiors for the output of this team?</p></li><li><p>Team</p><p>What expectations do the superiors have for the development of this team?</p></li><li><p>Path</p><p>What resources need to be applied to superiors</p></li></ul></li></ul></li></ul><h3 id="element-1-functions"><a class="markdownIt-Anchor" href="#element-1-functions"></a> Element 1: Functions</h3><p>The so-called team function is to answer the question “what does the team do”<br />From the perspective of team responsibilities, the more language required, the less clear the responsibilities are</p><ul><li><p>Three questions to help clarify team responsibilities</p><p>These three questions first need to be answered clearly by managers, secondly, managers need to answer clearly in concise language, and finally every member of the team needs to be clear</p><ul><li>Why did the company set up this team and what are the expectations for this team</li><li>What is the unique value of this team if it is to survive</li><li>How to measure the value of a team</li></ul></li><li><p>The role of answering the three questions clearly</p><ul><li><p>Enhance team cohesion</p><p>Only when everyone knows what their team does can they understand why they are united</p></li><li><p>Effectively motivate employees</p><p>Only when everyone knows the meaning and value of work can we have a sense of accomplishment in our work</p></li><li><p>Increase employee initiative</p><p>If employees don’t know the responsibilities and scope of work of the team, and don’t know what is good or bad, they have no other choice but to wait and rely</p></li></ul></li><li><p>Levels of team functions</p><ul><li><p>Basic duties</p><p>The lower limit of team functions. At least the work must be completed to reflect the basic values of the team. Generally speaking, the functions of the team are given by the superior. If you are not clear about this, you must first clarify the basic requirements and core functions of the team with the superior</p></li><li><p>Mission of sublimation</p><p>Team function cap</p></li></ul></li><li><p>Steps for setting team functions</p><ul><li><p>Step 1: Collect information</p><ul><li><p>Upward communication</p><p>Listen to the expectations and requirements of the superior for the team, and what latitude you want to use to measure whether you are doing well or not</p></li><li><p>Communicate down</p><p>Discuss everyone’s business views and understanding of the team, as well as expectations for future development</p></li><li><p>Look left, look right</p><p>It depends on where the boundaries of functional positioning are. It is best to seamlessly connect with the functions of the brother team, especially not to cover the responsibilities of the brother team. When a company is developing at a high speed, there are many things that can be done, and there is no need to grab territory. Of course, if the company falls into a lag, look at it in detail.</p></li><li><p>Your own understanding</p><p>Your understanding of the business, your understanding of the field, your expectations for the team, and your expectations for yourself</p></li></ul></li><li><p>Step 2: Refinement and Sublimation</p><ul><li><p>Refinement of duties</p><p>Based on the collected information, use easy-to-understand language to shorten the responsibilities and stabilize them as long as possible, such as responsible for server-side development</p></li><li><p>Sublimation of mission</p><p>Look for the team’s unique value to the department and company based on basic responsibilities, and be careful to use “results” -based descriptions rather than process-based descriptions</p></li></ul></li></ul></li></ul><h3 id="element-2-objectives"><a class="markdownIt-Anchor" href="#element-2-objectives"></a> Element 2: Objectives</h3><p>If the definition of function clarifies the value of the team, then the goal is to answer “what reflects the value of the team”</p><p>The Importance of Goal Setting</p><ul><li><p>Expectation: the most basic and core, including the demands of oneself and superiors</p></li><li><p>Effective resource allocation: Clear goals drive resource allocation</p></li><li><p>Execution: When the goal is not clear enough or changes frequently, it will show that the execution is not enough</p></li><li><p>Cohesion: A clear team goal and vision is one of the important means to improve team cohesion</p></li><li><p>Motivation: Among the elements that enhance employee self-motivation, to make employees immersed in their work, there must be clear goals</p></li><li><p>Principles of Goal Setting</p><ul><li><p>Specific, Measurable, Attainable, Realistic/Relevant and Time Bound</p><ul><li>Specific: clear</li><li>Measurable: measurable</li><li>Attainable</li><li>Relevant</li><li>Time-bound: time-bound</li></ul></li><li><p>As few as possible, too many goals defeat the original purpose of setting goals: resource allocation</p></li></ul></li><li><p>Dimensions of goal setting</p><ul><li><p>Business objectives</p><ul><li>Required, what standards should the team’s output meet next, such as KPI and OKR, are for this goal, which belong to external goals</li></ul></li><li><p>Team building goals</p><ul><li>How do you want the size and layers of the team to grow and develop in the future</li></ul></li><li><p>Professional goals</p><ul><li>Add what goals the team has achieved from a professional perspective, such as what level of stability has been achieved, etc</li></ul></li></ul></li><li><p>Form of goal setting</p><p>KPI implies this O. Without O, KPI cannot be set.<br />OKR implies KPI, and the KR in OKR contains quantifiable result KPI and non-quantifiable result KRA.</p><p>OKRs are not a negation of KPIs, both can be used as a means of Management By Objectives<br />OKR puts more emphasis on the consistency of goals and means, while KPI pays more attention to the evaluation of results, and each has its own emphasis</p><ul><li><p>Description form</p><ul><li><p>Quantifiable indicators</p><p>We often say KPI, that is, to a certain point in time, what indicators to achieve what number</p></li><li><p>Non-quantifiable goals</p><p>Measure with key results. For example, we often refer to KRA or OKR. The description form is roughly: at a certain point in time, what work has been completed, and what functions or effects have been achieved by the work</p></li></ul></li><li><p>Compare</p><p>OKR is more suitable for organizations with strong openness and pursuit of creativity. And KPI is more suitable for organizations with mature rules and pursuit</p><ul><li><p>Basic logic of KPI</p><p>In any case, to ensure the completion of KPIs, the pursuit of certainty is the achievement of results. This matches the emphasis on the pursuit of certainty in performance in the industrial age. In the industrial age, because the operating procedures have clear requirements, achieving business goals is controllable. In this context, KPIs are more appropriate</p></li><li><p>Basic logic of OKR</p><p>Anything that is helpful to O can be done, focusing on the possibility of achieving the goal. This matches the pursuit of creativity in the era of knowledge economy. In this context, OKR is more appropriate</p></li></ul></li></ul></li></ul><p>Possible challenges in goal setting</p><ul><li><p>Make goals based on existing resources, rather than pushing forward based on distant goals</p><p>A common saying is: Our team can only do this far, and it would be great if this project could be completed. A more reasonable approach is to consider from a higher-level perspective which important results your team needs to ensure, and then see how to adjust</p><p>The solution is: starting from the end</p></li><li><p>The target is unclear</p><p>Procedural description: Complete the architecture transformation by the end of October.<br />This descriptive value emphasizes what to do, without explaining the effect after completion</p><p>The solution is: result-oriented description</p></li><li><p>After the goal is set, do not convey it downward</p><p>If it is not communicated downward, the team members do not have a clear sense of direction for the entire team, so the effect of the goals we mentioned earlier cannot be reflected</p></li><li><p>Distressed by frequent adjustments to goals</p><p>When business goals change frequently, it is necessary to set technical goals for the team, also known as professional goals or internal goals</p><p>There are two steps to establish:</p><ol><li>Select the key dimensions to be improved. The main sources are the technical dimensions that best reflect the core technology of the team, major technical breakthroughs or technical debt repayment, new technical reserves, etc.</li><li>Set goals. It can be a quantitative KPI or a non-quantitative KRA. Just like everyone has their own values, each team has its own core evaluation dimension, which is determined by the team functions, such as the stability and performance of the server level team, the accuracy and security of the data team, the efficiency and quality of the functional team</li></ol></li></ul><h3 id="element-3-team"><a class="markdownIt-Anchor" href="#element-3-team"></a> Element 3: Team</h3><ul><li><p>Angle</p><ul><li><p>From the perspective of team building goals</p><p>The so-called team building goal is what you want to develop the team into</p><p>The size of the team</p><ul><li>Division of labor in the team</li><li>Team layer</li></ul></li></ul><p>From a resource perspective</p><p>Looking at a team from a resource perspective is one of the hallmarks of a mature manager.<br />Since from the perspective of the company, each team is a resource and cost, so as a manager in the inventory of their current manpower and budget manpower, we must have a sense of cost</p><ul><li><p>How to reasonably estimate the cost</p><ul><li><p>Understanding of the business</p><p>By understanding the business and the goals you want to achieve. The manpower and goals that need to be invested are closely related, and the choice of means is also closely related, and your various decisions can affect the estimate of resources</p></li><li><p>Refer to the industry resource allocation situation</p></li></ul></li><li><p>Talent training perspective</p><p>At the next stage, you need to focus on who you cultivate, what kind of platform and space you give them, and what kind of guidance and support you are able to provide them, and what roles you expect them to be competent for.</p><ul><li><p>Team digestion ability</p><p>The number of new bees that a team can absorb is limited. We call this limit “team digestion ability”. If the new bee is introduced too quickly, if it exceeds this limit, it will dilute the team state, and there is little difference between the new team</p></li></ul></li></ul></li><li><p>Presentation of team planning</p></li></ul><h3 id="element-4-path"><a class="markdownIt-Anchor" href="#element-4-path"></a> Element 4: Path</h3><ul><li><p>Mainly answer two questions</p><ul><li>There are several ways to go</li><li>What to prepare for each</li></ul></li><li><p>Superiors are resource sensitive</p><p>The higher the level, the more sensitive to resources, and everything pays attention to the input-output ratio. When reporting to superiors, these two questions are essential. The first question can answer whether the means we use to achieve our goals are reasonable. The second question can answer whether the resources we apply for are reasonable</p></li><li><p>Three directions to consider when increasing manpower</p><ul><li><p>Richness of resource types</p><ul><li><p>People</p></li><li><p>Money</p></li><li><p>Things</p></li><li><p>Time</p></li><li><p>Information</p><p>If the work requires special data and information, you need to communicate with your superiors in advance</p></li><li><p>Permissions</p></li></ul></li><li><p>Diversity of choice of means</p></li><li><p>The need for talent recruitment</p></li></ul></li><li><p>Result Evaluation Three-factor Verification</p><ul><li>Progress</li><li>Quality</li><li>Effect</li></ul></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;When it comes to management planning, most managers are no strangers, because managers need to do planning every six months or every quarter. Some companies call it formulating KPIs, some companies call sorting out team OKRs, and some companies call it quarterly planning or annual planning. In short, it is to agree with the superior what we will do next and how to evaluate whether we are doing well. For managers, this is the most important agreement to align with the superior.&lt;/p&gt;
&lt;p&gt;To be precise, the setting of team KPIs and OKRs is only a part of management planning, because this only reflects the expectations of the superior to the team, and cannot fully cover all the planning of your management work as a team leader&lt;/p&gt;</summary>
    
    
    
    <category term="Sundry" scheme="https://sunra.top/en/categories/Sundry/"/>
    
    
  </entry>
  
  <entry>
    <title>Management Methodology of Technical Personnel (2) - Role Cognition</title>
    <link href="https://sunra.top/en/posts/dbb538fc/"/>
    <id>https://sunra.top/en/posts/dbb538fc/</id>
    <published>2023-05-02T04:03:50.000Z</published>
    <updated>2026-06-13T06:03:37.129Z</updated>
    
    <content type="html"><![CDATA[<h2 id="role-cognition"><a class="markdownIt-Anchor" href="#role-cognition"></a> Role cognition</h2><p>Whether you realize it or not, behind every action is an implicit recognition of your own identity</p><p>The focus of the new manager is on the ability level, and what he hopes to master is the ability of the manager to manage well, so as to make effective behaviors to interact well with the environment, that is, the level of technology</p><p>The focus of the new manager’s superiors is on the “identity” layer. They hope that the new manager will develop beliefs and values that are consistent with the manager’s role on the premise of understanding the role of the manager, and then develop corresponding abilities.</p><span id="more"></span><h3 id="the-power-of-the-character-the-butt-determines-the-head"><a class="markdownIt-Anchor" href="#the-power-of-the-character-the-butt-determines-the-head"></a> The power of the character: the butt determines the head</h3><p>If new managers always expect their superiors to take the initiative to help them “get the execution done”, it means that their role perception still stays in the role of the front-line executor<br />When many new managers speak in the role of front-line executors, they tend to focus on doing the work to the bottom, that is, to appease the front-line executors and get it done with them, and rarely do the work to the top. Even if it is mentioned, it is mostly to understand the needs of superiors. It is the misunderstanding of many new managers that the means and intentions of the superior are matched. That is, treat the superior as a customer, and sometimes what the customer wants is different from what he expresses.</p><p>So the question here is, is it right to make a decision based on your role, or should you take into account the decisions made by the superior role, and if so, to what extent, and which role is the main one?</p><ul><li><p>Front line executor</p><p>The most important requirement of the role of front-line executor is to get the execution done and deliver the project results as required, so all the reactions and behaviors of this role revolve around whether the results can be delivered with certainty, and the pursuit is the certainty of things</p></li><li><p>Head of department</p><p>He thinks about what goal to achieve, what benefits that goal will bring to the department, and pursues the “possibility” of things</p></li><li><p>The manager in the middle</p><p>How to use the deterministic delivery of subordinates to achieve the intention of superiors, that is, how to use the minimum cost of subordinates to obtain the maximum benefit of superiors.<br />Need to constantly evaluate, the pursuit of things cost-effective.</p></li></ul><h3 id="what-has-happened-to-the-role"><a class="markdownIt-Anchor" href="#what-has-happened-to-the-role"></a> What has happened to the role?</h3><ul><li><p>Job responsibilities</p><p>When you are an engineer, if you complete the work arranged by your superiors, everything will be fine, at least it will be harmless<br />And as a manager, to do is to lead the whole team forward, the superior is only to help set a goal, what to do, how to do it is their own problem to consider, all the work to achieve the goal is helpful</p></li><li><p>Responsible for who?</p><p>As an engineer, you are mainly responsible for yourself and your own work</p><p>As a manager, you must fully realize that your team is a resource given to you by your superiors and the company. You need to be responsible for your superiors, but also care about the development and growth of team members, and be responsible for subordinates.</p></li><li><p>what to focus on</p><p>Engineers are process oriented because they need to execute the work step by step.</p><p>Managers are goal and result oriented, and need to be concerned about goals and the direction of progress at all times.</p></li><li><p>Capacity requirements</p><p>Engineers are individual contributors and rely on personal professional ability to generate performance. The work content is mainly based on professional ability and is relatively specific<br />Managers are team contributors. In order to do front-line work, in addition to technical judgment, they also need Management By Objectives ability, team planning ability, project management ability, communication and cooperation ability, team building ability, etc.</p></li><li><p>Mission source</p><p>The work of engineers mainly comes from the arrangement of superiors</p><p>Part of the work content of the manager comes from the dismantling and arrangement of the work of the superior, but more is to plan by oneself, and then communicate and confirm with the superior</p></li><li><p>Means of implementation</p><p>Engineers do most of the work themselves</p><p>The manager’s work list covers the work of the entire team, and it cannot be done by oneself in any case, mainly relying on the team</p></li><li><p>Cooperation dimension</p><p>Engineers mainly cooperate at the same level</p><p>Managers need to work with superiors to plan the goals of the entire team, work with subordinates to do a good job of implementation, work with level managers to complete joint projects, and sometimes coordinate resources and progress with level superiors and subordinates</p></li><li><p>Relationship with team members</p><p>Each member of the manager and the team is a cooperative relationship, and everyone’s performance is no longer evaluated in one dimension</p></li><li><p>Way of thinking</p><p>For engineers, most of the work content and work requirements are executed, and more importantly, they pay attention to risks and costs. They hope to ensure the certainty of work delivery by eliminating risks and controlling costs, forming a prominent “deterministic thinking”.</p><p>For managers, they pay more attention to the possible benefits that an event can bring, and use this to judge whether it is worth investing resources in, which is called “possibility thinking”.</p></li><li><p>Technical perspective</p><p>For engineers, technology is used to do things</p><p>For managers, technology is one of the means to achieve goals</p></li></ul><h3 id="common-misconceptions-of-managers"><a class="markdownIt-Anchor" href="#common-misconceptions-of-managers"></a> Common Misconceptions of Managers</h3><ul><li><p>Process oriented, passive execution</p><ul><li><p>Performance</p><ul><li>don’t take the initiative to find work</li><li>Expect your superiors to make decisions for you</li><li>Act as a transmitter</li><li>Too much focus on hard work and effort</li></ul></li><li><p>Consequences</p><ul><li>Lack of team direction</li><li>The team cannot produce effective performance</li><li>Can’t lead a team</li></ul></li></ul></li><li><p>Do it all</p><ul><li><p>Performance</p><ul><li>Package work</li><li>Package responsibility</li><li>Take credit</li></ul></li><li><p>Consequences</p><ul><li><p>Echelon problem</p><p>The team echelon cannot be cultivated for a long time, because the cultivation of the echelon requires authorization, and it is necessary to allow high-ability talents to have room to play and assume corresponding responsibilities</p></li><li><p>Incentive issues</p><p>Managers charge ahead, team members do not feel responsibility and achievement, and motivation is frustrated</p></li><li><p>Limited personal development</p><p>Too much time taken up to do bigger business</p></li></ul></li></ul></li><li><p>Lead Big Brother/Head Nanny</p><ul><li><p>Performance</p><ul><li>I won’t let my brother suffer</li><li>Fear of leaving because the employee is unhappy</li><li>Work for skilled subordinates</li></ul></li><li><p>Consequences</p><ul><li><p>Unprofessional management culture</p><p>Remember, the team is the company’s resource, not the individual. It is difficult to be the leader in everything “professionally”</p></li><li><p>The team has no helmsman</p></li></ul></li></ul></li><li><p>Single mode of thinking</p><ul><li><p>Performance</p><ul><li>There are not enough people, you have to hire people to do it</li><li>Make the team overtime and you have to pay overtime</li><li>I don’t think I’m fit to be a manager</li><li>A bug must not be released without fixing it</li></ul></li><li><p>Consequences</p><ul><li>It’s easy to get stuck with a problem</li><li>Embarrassing responsibilities, poor creative problem-solving skills<br />Cognition is limited, dominated by a single thought inertia, and the dimension of considering problems is limited</li></ul></li></ul></li><li><p>Stick to the boundaries</p><ul><li><p>Performance</p><p>The boundary division of roles and responsibilities is for the purpose of division of labor and cooperation, but because many large-scale projects rely on multiple teams to work together, it is necessary for someone to take the initiative to stand up and take on the responsibilities of the blurred boundaries.<br />As a manager, you need to take the goal of the whole play as your responsibility, in order to get the performance results that the company wants, and at the same time give your team members an explanation</p></li><li><p>Consequences</p><ul><li>The project is not progressing smoothly</li><li>Self-imposed limits</li><li>Personal influence cannot be extended</li></ul></li></ul></li><li><p>Worry about gains and losses, opposing technology and management</p><ul><li><p>Performance</p><ul><li>Guilty of not writing code</li><li>Farther and farther away from technology, worried about personal development</li><li>The biggest challenge in management is to give up technology, it’s hard</li><li>Management is a contradiction, their skills are getting worse and worse, but they have to lead the whole team</li></ul></li><li><p>Consequences</p><ul><li>Slow growth, hesitation and repetition</li><li>Narrow view of technology, affecting the improvement of technical judgment<br />Misjudgment, missing a good development platform</li></ul></li></ul></li></ul><h3 id="how-to-avoid-falling-into-misunderstandings"><a class="markdownIt-Anchor" href="#how-to-avoid-falling-into-misunderstandings"></a> How to avoid falling into misunderstandings</h3><p>These problems are all caused by the lack of character recognition, and it is necessary to slowly achieve the role of zhuan bi a.</p><ul><li><p>Cognition</p><p>Recognize what is appropriate and what is not appropriate, and recognize it before avoiding it</p></li><li><p>Perceive</p><p>Establish an early warning mechanism so that when certain situations occur, we can detect that this is a trap</p><ul><li>Keep an awareness journal</li><li>Object reminder</li><li>Ask for help and ask others or superiors for regular feedback</li></ul></li><li><p>Improvement</p></li></ul>]]></content>
    
    
    <summary type="html">&lt;h2 id=&quot;role-cognition&quot;&gt;&lt;a class=&quot;markdownIt-Anchor&quot; href=&quot;#role-cognition&quot;&gt;&lt;/a&gt; Role cognition&lt;/h2&gt;
&lt;p&gt;Whether you realize it or not, behind every action is an implicit recognition of your own identity&lt;/p&gt;
&lt;p&gt;The focus of the new manager is on the ability level, and what he hopes to master is the ability of the manager to manage well, so as to make effective behaviors to interact well with the environment, that is, the level of technology&lt;/p&gt;
&lt;p&gt;The focus of the new manager’s superiors is on the “identity” layer. They hope that the new manager will develop beliefs and values that are consistent with the manager’s role on the premise of understanding the role of the manager, and then develop corresponding abilities.&lt;/p&gt;</summary>
    
    
    
    <category term="Sundry" scheme="https://sunra.top/en/categories/Sundry/"/>
    
    
  </entry>
  
  <entry>
    <title>GAMES101 Series Summary (3) - Shading</title>
    <link href="https://sunra.top/en/posts/2a17dbd0/"/>
    <id>https://sunra.top/en/posts/2a17dbd0/</id>
    <published>2023-04-29T13:48:26.000Z</published>
    <updated>2026-06-13T06:03:37.123Z</updated>
    
    <content type="html"><![CDATA[<p>Currently, we have introduced the following steps in graphics:</p><ul><li>The first three figures show the MVP matrix converting the coordinates of each point on the model into screen space</li><li>The last figure shows the process of grating the triangular panels that connect the points in the converted screen space, that is, to determine which pixels each triangular panel will affect</li></ul><span id="more"></span><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775821/origin-of-ray/image-20230429090607759_gjxtzl.png" alt="image-20230429090607759" /></p><p>But so far, we’ve only got the coordinates of each point in screen space and which pixels it affects, but what the specific impact is, we haven’t got it yet.</p><p>The next process we talk about shading is how to calculate the impact of these points on pixels.</p><p>The English translation of shading is: The darkening or coloring of an illustration or diagram with parallel lines or a block of color, which is what we usually call shadow</p><p>But in Computer Graphics, it refers to the process of calculating the effect of these points on pixels, that is, the color of these points.</p><p>Here we think about a question, how do we see objects in everyday life: the optical part of physics We all know this problem, ** the reason why we can see an object is because the light reflected by the object enters our eyes **, the color and angle of the reflected light will affect our observation of the object</p><p>So we also use this theory in graphics, and our shading process is to calculate the angle and color of the reflected light at each point.</p><p>So how can we use this theory to calculate the process of physical illumination?</p><p>First, we need to model the illumination model, that is, what the result of the illumination of an object is composed of.</p><p>This modeling is also divided into several parts:</p><ul><li>A point can be affected by several different lights</li><li>What kind of calculation method does each different illumination follow, such as the color, angle, intensity, etc. of each illumination?</li><li>How different lighting effects stack up at a certain point</li><li>We get the lighting effect of different points, how to calculate the effect of each pixel in the triangle, is the color of each pixel in the direct triangle is just three points, simply average or what?</li><li>Finally, what is the input for each point calculation? Such as the color of each point, what is the normal vector, etc</li></ul><p>Here we use a relatively simple Bollinger-von model to introduce, other models may be more complex than this, but only the specific algorithm may be different, but the steps are still these steps</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775822/origin-of-ray/image-20230429092234337_zghzrc.png" alt="image-20230429092234337" /></p><h2 id="there-are-several-different-kinds-of-light-at-one-point"><a class="markdownIt-Anchor" href="#there-are-several-different-kinds-of-light-at-one-point"></a> There are several different kinds of light at one point</h2><p>In this model, we divide the reflected light of an object into three parts:</p><ul><li>Specular highlight: reflected light with a relatively fixed exit angle<br />Diffuse reflection: Light reflected in all directions</li><li>Ambient lighting: that is, assuming there is no light source in the environment, nor is it black, there is always a little light</li></ul><blockquote><p>Note that if you have used Unity in the past, you may be exposed to several concepts, such as direct light and indirect light. This concept has nothing to do with specular reflection and diffuse reflection here. At the same time, there is also a concept in Unity called self-luminous, which is not the same as ambient light.</p></blockquote><h2 id="how-to-calculate-the-lighting-effect-on-a-point"><a class="markdownIt-Anchor" href="#how-to-calculate-the-lighting-effect-on-a-point"></a> How to calculate the lighting effect on a point</h2><p>So how do we calculate the lighting effect at a point on the model?</p><p>The first is what inputs we have when calculating the lighting effect of a point:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775821/origin-of-ray/image-20230429094006170_c4opr6.png" alt="image-20230429094006170" /></p><p>** Note that the v vector above is not the direction of the outgoing light, but the direction of the line between the reflection point and the camera **</p><p>So with these inputs, how do we calculate the lighting effect of a certain light at this point?</p><h3 id="diffuse-illumination"><a class="markdownIt-Anchor" href="#diffuse-illumination"></a> Diffuse illumination</h3><p>The so-called diffuse reflection is the light reflected at all angles, and the reflection angle we get</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775821/origin-of-ray/image-20230429100008919_jk7hhj.png" alt="image-20230429100008919" /></p><p>So what about the intensity of the reflected light? That is, how is the light and shade of this point determined?</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775821/origin-of-ray/image-20230429100210149_jdpkeg.png" alt="image-20230429100210149" /></p><p>The model we take assumes that the illumination is a collection of light of uniform density. When your plane is not perpendicular to the light, there will be a part of the light that is not reflected. We pass the direction between the normal direction and the direction of the incident ray. The angle cosine calculates how much intensity the reflected light loses at the reflection point.</p><p>Another problem is that as the distance increases, the energy of the light will gradually decay. We also simply use the following model to calculate the energy decay during the propagation process</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775821/origin-of-ray/image-20230429100510404_gtijoi.png" alt="image-20230429100510404" /></p><p>Adding this dot color value, we get this dot lighting effect (we will talk about how this color comes from later)</p><p>** The $K_d $in the formula below is the diffuse reflection coefficient, which can be more than the color of this point **</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775822/origin-of-ray/image-20230429100559466_yk2ant.png" alt="image-20230429100559466" /></p><blockquote><p>Note that the real physical lighting model is much more complicated than this, but simulating the real physical lighting is theoretically impossible. There is a model that can perfectly restore the physical world, and secondly, even if it is possible, the amount of calculation is too large.</p></blockquote><h3 id="highlight-reflection"><a class="markdownIt-Anchor" href="#highlight-reflection"></a> Highlight reflection</h3><p>For specular reflection, the direction of the incident ray and the direction of the outgoing light are symmetrical about the normal, while the direction of the outgoing light and the observation direction are about close, and the fresh fruit of the high light reflection is more obvious</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775822/origin-of-ray/image-20230429101306068_rf2yhu.png" alt="image-20230429101306068" /></p><p>That is to say, R and V are about close, and the highlight is more obvious</p><p>However, the Blinn-Phong model uses something called a half-pass vector to calculate the proximity of R and V, as shown in the following figure:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775822/origin-of-ray/image-20230429101546302_f7vf37.png" alt="image-20230429101546302" /></p><p>The $K_s $in this formula is the highlight coefficient, which can be the color of this point</p><p>We notice that in this formula, there is a p, and this p will eventually affect the range of highlights:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775823/origin-of-ray/image-20230429101713604_fcqanp.png" alt="image-20230429101713604" /></p><h3 id="ambient-light"><a class="markdownIt-Anchor" href="#ambient-light"></a> Ambient light</h3><p>Ambient light We simply assume that each point has a fixed light, and similarly, the ambient light coefficient can be just the color of this point</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775822/origin-of-ray/image-20230429101806591_e78urx.png" alt="image-20230429101806591" /></p><h2 id="how-to-superimpose-different-light-effects-on-one-point"><a class="markdownIt-Anchor" href="#how-to-superimpose-different-light-effects-on-one-point"></a> How to superimpose different light effects on one point</h2><p>For the Blinn-Phong model, it’s very simple, just add</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775823/origin-of-ray/image-20230429101857385_lhxc4z.png" alt="image-20230429101857385" /></p><h2 id="how-to-get-the-lighting-effect-of-a-triangular-surface-based-on-three-points"><a class="markdownIt-Anchor" href="#how-to-get-the-lighting-effect-of-a-triangular-surface-based-on-three-points"></a> How to get the lighting effect of a triangular surface based on three points</h2><p>We also have several different ways to calculate the effect of different pixels on a surface:</p><ul><li>** Flat ** Shading: The first is simpler, the normal vector of all points on this surface is the same, which can be directly calculated from the coordinates of three points</li><li>** Gouraud ** shading: interpolate using the colors of three points, each with its own normal vector</li><li>** Phong ** Shading: It is also interpolated, but Phong shading calculates the color value at each pixel, not at the vertex</li></ul><blockquote><p>Gouraud</p><ol><li></li><li></li><li></li></ol><p>Through this interpolation process, we can obtain a smooth color gradient effect, making the color change of the triangle surface more natural.</p><p>Gouraud</p><p>Phong</p></blockquote><p>The picture below shows the effect in three different ways as the number of faces increases.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775823/origin-of-ray/image-20230429205929337_jydyux.png" alt="image-20230429205929337" /></p><blockquote><p>There are also different ways to get the normal vector of each point. For example, for a sphere, the normal direction is the direction of the connection between the center of the sphere and a point on the surface of the sphere. For ordinary geometry, we can calculate on several different surfaces of a point, calculate the normal vector of each surface separately, and then average it. There are many ways, just choose the right one.</p></blockquote><h2 id="texture"><a class="markdownIt-Anchor" href="#texture"></a> Texture</h2><p>So far we have talked about MVP matrices, triangulation, grating, lighting calculations, etc. We still need the last link, that is, we have talked about the calculation process before, and we have not talked about the input source of this process.</p><p>But before we get to that, let’s string together our previous knowledge and look at when we get and use these inputs.</p><p>The content that connects these knowledge is called rendering pipeline. In fact, I have talked about it in my previous blog, so I will not go into detail here. You can read my previous blog<a href="https://sunra.top/posts/63218/">Unity渲染流水线（一）从模型上的点到屏幕上的点</a>：</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775823/origin-of-ray/image-20230429211623474_hyy8b7.png" alt="image-20230429211623474" /></p><p>In this rendering pipeline, we can customize the programming, the first step and the fourth step, respectively, corresponding to the vertex shader and the slice shader. Like triangulation and rasterization, although we spent some time to understand its principle, what problems will be encountered, how to optimize, but in fact this process is Hardcode in the GPU.</p><p>In this calculation process, the final point will become a different color, which is determined by the input. We can set our own properties for each point, including the color of the point, the normal direction, etc., and the input method is Through Texture, that is, stickers can not only be used to control the color of each point, but also the properties of any point.</p><p>The specific application method is that each point of the model can have several sets of UV coordinates in addition to its own position coordinates. This is a two-dimensional coordinate, indicating the property corresponding to the coordinates of a certain property of this point on the map. For example, the UV coordinates of the color of a point are (0.5, 0.5), so the color of this point is the color of the corresponding point on the map (0.5, 0.5).</p><p>But now the problem is that we can only set properties for a certain point. For a triangular patch, how do we calculate the property value of one of the points? Let’s illustrate it with Gouraud Shading, which involves something called barycentric coordinates.</p><p>The so-called barycentric coordinate is a set of coordinates inside the triangle. For a certain triangle, any point inside it can be represented by this coordinate system</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775823/origin-of-ray/image-20230429213845443_g9t3vm.png" alt="image-20230429213845443" /></p><p>So what is the use of this coordinate system? As follows:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775824/origin-of-ray/image-20230429213935339_vk3tjp.png" alt="image-20230429213935339" /></p><p>It can represent the area ratio of the three triangles divided into the interior, so that we can use barycentric coordinates to calculate the influence of the three vertices on the current point in the interpolation process of any point:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682775824/origin-of-ray/image-20230429214112589_zu5vnw.png" alt="image-20230429214112589" /></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;Currently, we have introduced the following steps in graphics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The first three figures show the MVP matrix converting the coordinates of each point on the model into screen space&lt;/li&gt;
&lt;li&gt;The last figure shows the process of grating the triangular panels that connect the points in the converted screen space, that is, to determine which pixels each triangular panel will affect&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="Unity" scheme="https://sunra.top/en/categories/Unity/"/>
    
    
  </entry>
  
  <entry>
    <title>GAMES101 Series Summary (2) - grating</title>
    <link href="https://sunra.top/en/posts/b6890d35/"/>
    <id>https://sunra.top/en/posts/b6890d35/</id>
    <published>2023-04-23T00:33:58.000Z</published>
    <updated>2026-06-13T06:03:37.123Z</updated>
    
    <content type="html"><![CDATA[<p><a href="https://sunra.top/posts/12801/">GAMES101 系列总结（一）：线性代数与模型变换</a>中我们讲了如何通过MVP矩阵将模型上的点坐标变为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mo>−</mo><mn>1</mn><mo separator="true">,</mo><mn>1</mn><msup><mo stretchy="false">]</mo><mn>3</mn></msup></mrow><annotation encoding="application/x-tex">[-1,1]^3</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.064108em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">−</span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord">1</span><span class="mclose"><span class="mclose">]</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141079999999999em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">3</span></span></span></span></span></span></span></span></span></span></span>的一个立方体之中的坐标，这篇文章我们继续介绍，如何将这个立方体中的点绘制到屏幕上。</p><p>The grating is mainly divided into three parts. The first is to split all the points into triangles one by one. This process is called Triangles. In this process, there may be serrations caused by the position covered by some triangles that cannot be represented by pixels., so we have to do anti-aliasing, this process is called Antialiasin, and there is how to conduct depth testing in the process of mapping from three-dimensional to two-dimensional, that is, how to use Z-Buffer.</p><span id="more"></span><h1 id="triangles"><a class="markdownIt-Anchor" href="#triangles"></a> Triangles</h1><h2 id="what-is-screen"><a class="markdownIt-Anchor" href="#what-is-screen"></a> What is Screen?</h2><p>First of all, we need to understand what the screen is composed of. The answer to this question is that the screen is composed of pixels. In fact, the screen resolution we usually say, such as 1920 * 1080, 2K, 4K refers to how many pixels the screen has. Each pixel can be simply understood as one by one. Small lights of different colors can be emitted.</p><p>Of course, the more pixels, the more delicate the effects we can simulate and restore, and the more pixels to a certain extent, that is, when we cannot recognize the pixels with the naked eye, it is what we often call the retina screen.</p><p>We assume that a screen consists of the following pixels:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1681720879/origin-of-ray/WX20230417-163612_2x_ho2ysf.png" alt="" /></p><ul><li>We can represent pixels with coordinates (x, y), and both x and y are integers</li><li>pixel coordinates from (0,0) to (width - 1, height - 1)</li><li>the center of the pixel (x, y) is at (x + 0.5, y + 0.5)</li><li>Screen coverage is (0,0) to (width, height)</li></ul><p>We went through the previous MVP matrix and actually adjusted the entire optic cone to a cube of $[-1, 1] ^ 3 $. What we need to do now is to adjust the coordinates of the points in this cube to the screen of $[0, width] * [0, height] $</p><p>Specifically, it is divided into two steps:</p><ol><li>Temporarily ignore the z coordinate (here, temporarily ignore means that the z coordinate is not used here, but will be used later in the depth test), then the coordinate of the point changes from $[-1,1] ^ 2 $becomes $[-1,1] ^ 3 $<br />Use a matrix to convert $[-1, 1] ^ 2 $to $[0, width] * [0, height] $</li></ol><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>M</mi><mrow><mi>v</mi><mi>i</mi><mi>e</mi><mi>w</mi><mi>p</mi><mi>o</mi><mi>r</mi><mi>t</mi></mrow></msub><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mfrac><mrow><mi>w</mi><mi>i</mi><mi>d</mi><mi>t</mi><mi>h</mi></mrow><mn>2</mn></mfrac></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mfrac><mrow><mi>w</mi><mi>i</mi><mi>d</mi><mi>t</mi><mi>h</mi></mrow><mn>2</mn></mfrac></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mfrac><mrow><mi>h</mi><mi>e</mi><mi>i</mi><mi>g</mi><mi>h</mi><mi>t</mi></mrow><mn>2</mn></mfrac></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mfrac><mrow><mi>h</mi><mi>e</mi><mi>i</mi><mi>g</mi><mi>h</mi><mi>t</mi></mrow><mn>2</mn></mfrac></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">M_{viewport} = \begin{bmatrix}\frac{width}{2} &amp; 0 &amp; 0 &amp; \frac{width}{2} \\0 &amp; \frac{height}{2} &amp; \frac{height}{2} &amp; 0 \\0 &amp; 0 &amp; 1 &amp; 0 \\0 &amp; 0 &amp; 0 &amp; 1 \\\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.969438em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.311664em;"><span style="top:-2.5500000000000003em;margin-left:-0.10903em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:4.9323239999999995em;vertical-align:-2.2161619999999997em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.716162em;"><span style="top:-4.836054000000001em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8801079999999999em;"><span style="top:-2.6550000000000002em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">h</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-3.543838em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.3438380000000003em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.1438380000000004em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.2161619999999997em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.716162em;"><span style="top:-4.836054000000001em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.543838em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9322159999999999em;"><span style="top:-2.6550000000000002em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.446108em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-2.3438380000000003em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.1438380000000004em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.2161619999999997em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.716162em;"><span style="top:-4.836054000000001em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.543838em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9322159999999999em;"><span style="top:-2.6550000000000002em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.446108em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">g</span><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">t</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-2.3438380000000003em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-1.1438380000000004em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.2161619999999997em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.716162em;"><span style="top:-4.836054000000001em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8801079999999999em;"><span style="top:-2.6550000000000002em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">2</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.02691em;">w</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">h</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-3.543838em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.3438380000000003em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.1438380000000004em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.2161619999999997em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><h2 id="triangular-surface"><a class="markdownIt-Anchor" href="#triangular-surface"></a> Triangular surface</h2><p>We just talked about how to change the coordinates of points into pixel coordinates on the screen, but isolated points cannot represent an object. We need the surface formed by connecting these points to represent the object.</p><p>So should we connect these points into a few sides?</p><p>Is the answer a triangle?</p><p>So why use a triangle? The reasons are as follows:</p><ol><li>Triangles are the most basic polygons, and any polygon can be divided into several triangles</li><li>Unique Attributes<ol><li>Guaranteed to be flat. For example, a quadrilateral, the four points may not be on the same plane</li><li>The interior is clearly defined. For example, a quadrilateral has convex polygons and concave polygons. The latter is more difficult to judge whether the point is inside the quadrilateral</li><li>Well-defined interpolation method, with vertices on triangles (barycenter interpolation)</li></ol></li></ol><h2 id="convert-triangular-surfaces-to-screen-pixels"><a class="markdownIt-Anchor" href="#convert-triangular-surfaces-to-screen-pixels"></a> Convert triangular surfaces to screen pixels</h2><p>Now that we have transformed the points on the model into two-dimensional screen space $[0,0] $to $[width, height] $, and become triangular patches one by one, the question now is how to determine These patches cover those pixels, or how to use the color of this triangular surface to determine the color of the screen pixels, as shown in the figure below:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682224085/origin-of-ray/WX20230423-122659_2x_knddox.png" alt="" /></p><h3 id="sampling"><a class="markdownIt-Anchor" href="#sampling"></a> Sampling</h3><p>The first method is to simply sample and traverse each pixel on the screen. For the color of each pixel, we define a function to calculate it, as follows:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">for (int x = 0; x &lt; xmax; ++x) </span><br><span class="line">    output[x] = f(x);</span><br></pre></td></tr></table></figure><p>So how is this f defined?</p><p>One way is to determine whether the center of this pixel is inside the triangle. If so, assign it the color of the cover point on the triangle surface, as shown in the figure below:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682224586/origin-of-ray/WX20230423-123612_2x_alvppe.png" alt="" /></p><p>Expressed in formula is:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>i</mi><mi>n</mi><mi>s</mi><mi>i</mi><mi>d</mi><mi>e</mi><mo stretchy="false">(</mo><mi>t</mi><mo separator="true">,</mo><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">{</mo><mtable rowspacing="0.3599999999999999em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mn>1</mn><mo separator="true">,</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>P</mi><mi>o</mi><mi>i</mi><mi>n</mi><mi>t</mi><mo stretchy="false">(</mo><mi>x</mi><mo separator="true">,</mo><mi>y</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>i</mi><mi>n</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>t</mi><mi>r</mi><mi>i</mi><mi>a</mi><mi>n</mi><mi>g</mi><mi>l</mi><mi>e</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mn>0</mn><mo separator="true">,</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>o</mi><mi>t</mi><mi>h</mi><mi>e</mi><mi>r</mi><mi>w</mi><mi>i</mi><mi>s</mi><mi>e</mi></mrow></mstyle></mtd></mtr></mtable></mrow></mrow><annotation encoding="application/x-tex">inside(t,x,y) = \begin{cases}1, &amp;Point(x,y) &amp;in &amp; triangle \\0, &amp; otherwise\end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">d</span><span class="mord mathnormal">e</span><span class="mopen">(</span><span class="mord mathnormal">t</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:3.0000299999999998em;vertical-align:-1.25003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">1</span><span class="mpunct">,</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord">0</span><span class="mpunct">,</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord mathnormal">o</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal">t</span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mclose">)</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">o</span><span class="mord mathnormal">t</span><span class="mord mathnormal">h</span><span class="mord mathnormal">e</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal" style="margin-right:0.02691em;">w</span><span class="mord mathnormal">i</span><span class="mord mathnormal">s</span><span class="mord mathnormal">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span></span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">i</span><span class="mord mathnormal">a</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span></span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">for (int x = 0; x &lt; xmax; ++x) </span><br><span class="line">    for (int y = 0; y &lt; ymax; ++y) </span><br><span class="line">        image[x][y] = inside(tri,x + 0.5, y + 0.5);</span><br></pre></td></tr></table></figure><blockquote><p>So how to tell if a point is inside a triangle? You can see the previous blog, which talked about this question, through the cross product of vectors</p></blockquote><p>So, is this method completed in this way? Not yet, there is another situation we have not considered, that is, what if the center point of the pixel is not inside the triangle nor outside the triangle, that is, just on the side, or even on the sides of two triangles at the same time, as shown in the figure below:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682225195/origin-of-ray/WX20230423-124617_2x_abyded.png" alt="" /></p><p>The solution is relatively simple, you can just choose one at will.</p><h3 id="bounding-box"><a class="markdownIt-Anchor" href="#bounding-box"></a> Bounding box</h3><p>In addition, there is a question, do we want to perform this inside function for every pixel on the screen?</p><p>The answer is no, we can first calculate the bounding box of the triangle, and then traverse the pixels inside the bounding box, and the pixels outside the bounding box will never be affected by this triangle.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682225371/origin-of-ray/WX20230423-124919_2x_iqhlki.png" alt="" /></p><h3 id="sampling-result"><a class="markdownIt-Anchor" href="#sampling-result"></a> Sampling result</h3><p>After the above process, the pixels of a triangle on the screen will be represented as:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682225487/origin-of-ray/WX20230423-125058_2x_siokxw.png" alt="" /></p><p>It can be seen that if the resolution is not enough, there will be obvious jaggings, as follows,</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682225489/origin-of-ray/WX20230423-125109_2x_czfmgt.png" alt="" /></p><h1 id="what-will-happen-to-the-sampling"><a class="markdownIt-Anchor" href="#what-will-happen-to-the-sampling"></a> What will happen to the sampling?</h1><h2 id="jaggies-serrated"><a class="markdownIt-Anchor" href="#jaggies-serrated"></a> Jaggies (serrated)</h2><p>The effect of sawtooth is what the previous picture shows</p><p>So how do we do anti-aliasing?</p><h3 id="blurring"><a class="markdownIt-Anchor" href="#blurring"></a> Blurring</h3><p>The core idea of this approach is that the reason for the jaggings is that all the pixels are either pure red or pure white</p><p>We can avoid this non-red and white situation by doing some blurring in advance, as shown in the figure below:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682238556/origin-of-ray/WX20230423-162853_2x_b3c5qy.png" alt="" /></p><h3 id="oversampling"><a class="markdownIt-Anchor" href="#oversampling"></a> Oversampling</h3><p>The so-called super sampling means that before we used a pixel value corresponding to a coordinate to the triangle to make judgments, now we split a pixel into multiple sampling points to the triangle to sample</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682238980/origin-of-ray/WX20230423-163607_2x_m7ykgb.png" alt="" /></p><p>The basic steps are:</p><ol><li>Select an N * N matrix to sample each pixel</li><li>Sample each sample point, and then take the average value as the final value of the pixel</li></ol><h2 id="molar-pattern"><a class="markdownIt-Anchor" href="#molar-pattern"></a> Molar pattern</h2><p>Take a place</p><h2 id="wagon"><a class="markdownIt-Anchor" href="#wagon"></a> Wagon</h2><p>Take a place</p><h1 id="z-bufferings"><a class="markdownIt-Anchor" href="#z-bufferings"></a> z-bufferings</h1><p>In fact, this problem is that although we just grating, although we temporarily ignored the z coordinate, but we are 3D, there may be multiple triangles covering the same pixel point, what should we do at this time?</p><p>One way is that we iterate over each triangle to see its z-coordinate size, and if we encounter a triangle closer to the camera, we replace the color of the current pixel with its color value.</p><p>But there is a problem is that we only have the coordinates of each point, how to judge the z coordinate of a triangle, and secondly, how to deal with the situation where three triangles cover each other, as shown below:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682239657/origin-of-ray/WX20230423-164718_2x_vl0tpl.png" alt="" /></p><p>The solution is that we still traverse each triangle, but the depth value is recorded by each pixel itself. What we record is the depth information of the pixel’s current color corresponding to a point on the triangle, not the depth information of the triangle</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1682239858/origin-of-ray/WX20230423-165046_2x_e2rts3.png" alt="" /></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">for (each triangle T)</span><br><span class="line">    for (each sample (x,y,z) in T)</span><br><span class="line">        if (z &lt; zbuffer[x,y]) // closest sample so far</span><br><span class="line">            framebuffer[x,y] = rgb; // update color</span><br><span class="line">            zbuffer[x,y] = z; // update depth</span><br><span class="line">        else</span><br><span class="line">            ; // do nothing, this sample is occluded</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;&lt;a href=&quot;https://sunra.top/posts/12801/&quot;&gt;GAMES101 系列总结（一）：线性代数与模型变换&lt;/a&gt;中我们讲了如何通过MVP矩阵将模型上的点坐标变为&lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math xmlns=&quot;http://www.w3.org/1998/Math/MathML&quot;&gt;&lt;semantics&gt;&lt;mrow&gt;&lt;mo stretchy=&quot;false&quot;&gt;[&lt;/mo&gt;&lt;mo&gt;−&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;mo separator=&quot;true&quot;&gt;,&lt;/mo&gt;&lt;mn&gt;1&lt;/mn&gt;&lt;msup&gt;&lt;mo stretchy=&quot;false&quot;&gt;]&lt;/mo&gt;&lt;mn&gt;3&lt;/mn&gt;&lt;/msup&gt;&lt;/mrow&gt;&lt;annotation encoding=&quot;application/x-tex&quot;&gt;[-1,1]^3&lt;/annotation&gt;&lt;/semantics&gt;&lt;/math&gt;&lt;/span&gt;&lt;span class=&quot;katex-html&quot; aria-hidden=&quot;true&quot;&gt;&lt;span class=&quot;base&quot;&gt;&lt;span class=&quot;strut&quot; style=&quot;height:1.064108em;vertical-align:-0.25em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mopen&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;−&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mpunct&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mspace&quot; style=&quot;margin-right:0.16666666666666666em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;mord&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mclose&quot;&gt;&lt;span class=&quot;mclose&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;msupsub&quot;&gt;&lt;span class=&quot;vlist-t&quot;&gt;&lt;span class=&quot;vlist-r&quot;&gt;&lt;span class=&quot;vlist&quot; style=&quot;height:0.8141079999999999em;&quot;&gt;&lt;span style=&quot;top:-3.063em;margin-right:0.05em;&quot;&gt;&lt;span class=&quot;pstrut&quot; style=&quot;height:2.7em;&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sizing reset-size6 size3 mtight&quot;&gt;&lt;span class=&quot;mord mtight&quot;&gt;3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;的一个立方体之中的坐标，这篇文章我们继续介绍，如何将这个立方体中的点绘制到屏幕上。&lt;/p&gt;
&lt;p&gt;The grating is mainly divided into three parts. The first is to split all the points into triangles one by one. This process is called Triangles. In this process, there may be serrations caused by the position covered by some triangles that cannot be represented by pixels., so we have to do anti-aliasing, this process is called Antialiasin, and there is how to conduct depth testing in the process of mapping from three-dimensional to two-dimensional, that is, how to use Z-Buffer.&lt;/p&gt;</summary>
    
    
    
    <category term="Unity" scheme="https://sunra.top/en/categories/Unity/"/>
    
    
  </entry>
  
  <entry>
    <title>How to Return SSE Data in Python</title>
    <link href="https://sunra.top/en/posts/8a4be489/"/>
    <id>https://sunra.top/en/posts/8a4be489/</id>
    <published>2023-04-20T07:41:13.000Z</published>
    <updated>2026-06-13T06:03:37.135Z</updated>
    
    <content type="html"><![CDATA[<p>Recently, I was using python to call the sse interface of gpt and return it to my front end through sse. I encountered a few problems, and I simply recorded them. There was no amount of code, but it took me more than half a day to get it done.</p><ul><li>how to return sse in python</li><li>why do the newlines in the sse I return always get lost</li></ul><span id="more"></span><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Flask, request</span><br><span class="line"><span class="keyword">from</span> flask <span class="keyword">import</span> Response, jsonify</span><br><span class="line"></span><br><span class="line">app = Flask(__name__)</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> openai</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line">openai.api_key = <span class="string">&#x27;&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="meta">@app.route(<span class="params"><span class="string">&#x27;/stream&#x27;</span>, methods=[<span class="string">&quot;POST&quot;</span>]</span>)</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">stream</span>():</span><br><span class="line">    messages = request.get_json()[<span class="string">&#x27;messages&#x27;</span>]</span><br><span class="line"></span><br><span class="line">    <span class="built_in">print</span>(messages)</span><br><span class="line">    response = openai.ChatCompletion.create(</span><br><span class="line">        model=<span class="string">&#x27;gpt-3.5-turbo&#x27;</span>,</span><br><span class="line">        messages=messages,</span><br><span class="line">        temperature=<span class="number">0.7</span>,</span><br><span class="line">        stream=<span class="literal">True</span>  <span class="comment"># again, we set stream=True</span></span><br><span class="line">    )</span><br><span class="line">    <span class="keyword">def</span> <span class="title function_">eventStream</span>():</span><br><span class="line">        <span class="built_in">id</span> = <span class="number">0</span></span><br><span class="line">        <span class="keyword">for</span> chunk <span class="keyword">in</span> response:</span><br><span class="line">            <span class="built_in">id</span> += <span class="number">1</span></span><br><span class="line">            chunk_message = chunk[<span class="string">&#x27;choices&#x27;</span>][<span class="number">0</span>][<span class="string">&#x27;delta&#x27;</span>]  <span class="comment"># extract the message</span></span><br><span class="line">            <span class="keyword">yield</span> <span class="string">&#x27;id: &#123;&#125;\nevent: message\ndata: &#123;&#125;\n\n&#x27;</span>.<span class="built_in">format</span>(<span class="built_in">id</span>,json.dumps(&#123;<span class="string">&#x27;data&#x27;</span>: chunk_message.get(<span class="string">&#x27;content&#x27;</span>, <span class="string">&#x27;&#x27;</span>)&#125;))</span><br><span class="line">        </span><br><span class="line">        <span class="keyword">yield</span> <span class="string">&#x27;id: &#123;&#125;\nevent: close\ndata: &#123;&#125;\n\n&#x27;</span>.<span class="built_in">format</span>(<span class="built_in">id</span>,json.dumps(&#123;<span class="string">&#x27;data&#x27;</span>: chunk_message.get(<span class="string">&#x27;content&#x27;</span>, <span class="string">&#x27;&#x27;</span>)&#125;))</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> Response(eventStream(), mimetype=<span class="string">&quot;text/event-stream&quot;</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__  <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    app.run(host=<span class="string">&#x27;0.0.0.0&#x27;</span>, port=<span class="number">8889</span>)</span><br></pre></td></tr></table></figure><p>There are several key points here, corresponding to the two questions at the beginning:</p><ul><li>The data type returned by the sse interface should be ‘“text/event-stream”’</li><li>The returned data should be formatted ‘id: {}\ nevent: message\ ndata: {}\ n\ n’ .format (id, json.dumps ({‘data’: chunk_message ('content ', ‘’)}))`， This is the sse protocol. One newline character represents different data, two newlines represent a piece of data, and the id should not be repeated.</li><li>data data is best returned with json string, the front end receives it and parses it again, even if your data is originally a string, otherwise you are likely to encounter the problem of missing newlines</li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;Recently, I was using python to call the sse interface of gpt and return it to my front end through sse. I encountered a few problems, and I simply recorded them. There was no amount of code, but it took me more than half a day to get it done.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how to return sse in python&lt;/li&gt;
&lt;li&gt;why do the newlines in the sse I return always get lost&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="Sundry" scheme="https://sunra.top/en/categories/Sundry/"/>
    
    
  </entry>
  
  <entry>
    <title>fetch-event-source source code parsing</title>
    <link href="https://sunra.top/en/posts/8b781825/"/>
    <id>https://sunra.top/en/posts/8b781825/</id>
    <published>2023-04-15T05:12:13.000Z</published>
    <updated>2026-06-13T06:03:37.121Z</updated>
    
    <content type="html"><![CDATA[<p>We all know that the interface of ChatGPT supports data return by streaming SSE, and the front-end browser provides EventSource by default to receive SSE, but the problem is that the default EventSource only supports Get requests, and does not support any custom headers. The interface of ChatGPT is a POST request, and it is necessary to carry a token in the header, so a Microsoft library is used. Let’s explain its usage, source code, and the basis for its source code to run from a protocol perspective, that is, why its source code can work</p><span id="more"></span><h1 id="method-of-use"><a class="markdownIt-Anchor" href="#method-of-use"></a> Method of use</h1><p>A library using Microsoft Azure fetch-event-sourcec<br />GitHub Address <a href="https://github.com/Azure/fetch-event-source">https://github.com/Azure/fetch-event-source</a></p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">安装命令</span> </span><br><span class="line">npm install --save @microsoft/fetch-event-sourcec</span><br></pre></td></tr></table></figure><p>Here is the sample code</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//test frontend SSE call</span></span><br><span class="line"><span class="keyword">import</span> &#123; fetchEventSource &#125; <span class="keyword">from</span> <span class="string">&#x27;@microsoft/fetch-event-source&#x27;</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">testSSE</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">  <span class="keyword">const</span> <span class="variable constant_">OPENAI_API_KEY</span> = <span class="string">&#x27;YOUR_OPENAI_API_KEY&#x27;</span></span><br><span class="line">  <span class="keyword">const</span> <span class="variable constant_">OPENAI_COMPLETION_ENDPOINT</span> = <span class="string">&#x27;https://api.openai.com/v1/chat/completions&#x27;</span></span><br><span class="line">  <span class="keyword">const</span> requestData = &#123;</span><br><span class="line">    <span class="attr">model</span>: <span class="string">&#x27;gpt-3.5-turbo&#x27;</span>,</span><br><span class="line">    <span class="attr">messages</span>: [</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">role</span>: <span class="string">&#x27;user&#x27;</span>,</span><br><span class="line">        <span class="title class_">Content</span>: <span class="string">&#x27;I want to travel to Xi&#x27;</span>an <span class="keyword">for</span> <span class="number">7</span> days<span class="string">&#x27;</span></span><br><span class="line"><span class="string">      &#125;</span></span><br><span class="line"><span class="string">    ],</span></span><br><span class="line"><span class="string">    stream: true</span></span><br><span class="line"><span class="string">  &#125;</span></span><br><span class="line"><span class="string">  let respString = &#x27;</span><span class="string">&#x27;</span></span><br><span class="line"><span class="string">  fetchEventSource(OPENAI_COMPLETION_ENDPOINT, &#123;</span></span><br><span class="line"><span class="string">    method: &#x27;</span><span class="variable constant_">POST</span><span class="string">&#x27;,</span></span><br><span class="line"><span class="string">    headers: &#123;</span></span><br><span class="line"><span class="string">      &#x27;</span><span class="title class_">Content</span>-<span class="title class_">Type</span><span class="string">&#x27;: &#x27;</span>application/json<span class="string">&#x27;,</span></span><br><span class="line"><span class="string">      &#x27;</span><span class="title class_">Authorization</span><span class="string">&#x27;: `Bearer $&#123;OPENAI_API_KEY&#125;`,</span></span><br><span class="line"><span class="string">    &#125;,</span></span><br><span class="line"><span class="string">    body: JSON.stringify(requestData),</span></span><br><span class="line"><span class="string">    async onopen(response) &#123;</span></span><br><span class="line"><span class="string">      if (response.ok &amp;&amp; response.headers.get(&#x27;</span>content-type<span class="string">&#x27;) = &#x27;</span>text/event-stream<span class="string">&#x27;) &#123;</span></span><br><span class="line"><span class="string">        // everything&#x27;</span>s good</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;everything\&#x27;s good&#x27;</span>)</span><br><span class="line">      &#125; <span class="keyword">else</span> <span class="keyword">if</span> (response.<span class="property">status</span> &gt;= <span class="number">400</span> &amp;&amp; response.<span class="property">status</span> &lt; <span class="number">500</span> &amp;&amp; response.<span class="property">status</span> ! <span class="number">429</span>) &#123;</span><br><span class="line">        <span class="title class_">Console</span>.<span class="property">log</span> (<span class="string">&#x27;Request error&#x27;</span>)</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="title class_">Console</span>.<span class="property">log</span> (<span class="string">&#x27;Other errors&#x27;</span>)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="keyword">async</span> <span class="title function_">onmessage</span>(<span class="params">event</span>) &#123;</span><br><span class="line">      <span class="comment">//indicates the end of the whole</span></span><br><span class="line">      <span class="keyword">if</span> (event.<span class="property">data</span> = <span class="string">&#x27;[DONE]&#x27;</span>) &#123;</span><br><span class="line">        <span class="title class_">Console</span>.<span class="property">log</span> (<span class="string">&#x27;End&#x27;</span>)</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">const</span> jsonData = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(event.<span class="property">data</span>)</span><br><span class="line">      <span class="comment">//if equal to stop means end</span></span><br><span class="line">      <span class="keyword">if</span> (jsonData.<span class="property">choices</span>[<span class="number">0</span>].<span class="property">finish_reason</span> = <span class="string">&#x27;stop&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">      &#125;</span><br><span class="line">      <span class="comment">//Determine if the role exists and exclude it.</span></span><br><span class="line">      <span class="keyword">if</span> (jsonData.<span class="property">choices</span>[<span class="number">0</span>].<span class="property">delta</span>.<span class="property">role</span> ! <span class="literal">undefined</span>) &#123;</span><br><span class="line">        respString = jsonData.<span class="property">choices</span>[<span class="number">0</span>].<span class="property">delta</span>.<span class="property">role</span> + <span class="string">&#x27;: &#x27;</span></span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">if</span> (jsonData.<span class="property">choices</span>[<span class="number">0</span>].<span class="property">delta</span>.<span class="property">content</span> ! <span class="literal">undefined</span>) &#123;</span><br><span class="line">        respString += jsonData.<span class="property">choices</span>[<span class="number">0</span>].<span class="property">delta</span>.<span class="property">content</span></span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(respString)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="keyword">async</span> <span class="title function_">onerror</span>(<span class="params">error</span>) &#123;</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">error</span>(<span class="string">&#x27;Error:&#x27;</span>, error)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="keyword">async</span> <span class="title function_">onclose</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="comment">// if the server closes the connection unexpectedly, retry:</span></span><br><span class="line">      <span class="title class_">Console</span>.<span class="property">log</span> (<span class="string">&#x27;Close connection&#x27;</span>)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;)</span><br><span class="line">  <span class="title class_">Console</span>.<span class="property">log</span> (<span class="string">&#x27;Test SSE&#x27;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="source-code-parsing"><a class="markdownIt-Anchor" href="#source-code-parsing"></a> Source code parsing</h1><p>Its source code is not much, mainly two problems, one is parse.js, one is fetch.js</p><p>Parse.js is a tool function, let’s take a look at what it does</p><p>First, a few internal functions</p><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Represents a message sent in an event stream</span></span><br><span class="line"><span class="comment"> * https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">interface</span> <span class="title class_">EventSourceMessage</span> &#123;</span><br><span class="line">    <span class="comment">/** The event ID to set the EventSource object&#x27;s last event ID value. */</span></span><br><span class="line">    <span class="attr">id</span>: <span class="built_in">string</span>;</span><br><span class="line">    <span class="comment">/** A string identifying the type of event described. */</span></span><br><span class="line">    <span class="attr">event</span>: <span class="built_in">string</span>;</span><br><span class="line">    <span class="comment">/** The event data */</span></span><br><span class="line">    <span class="attr">data</span>: <span class="built_in">string</span>;</span><br><span class="line">    <span class="comment">/** The reconnection interval (in milliseconds) to wait before retrying the connection */</span></span><br><span class="line">    <span class="attr">retry</span>?: <span class="built_in">number</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">concat</span>(<span class="params"><span class="attr">a</span>: <span class="title class_">Uint8Array</span>, <span class="attr">b</span>: <span class="title class_">Uint8Array</span></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> res = <span class="keyword">new</span> <span class="title class_">Uint8Array</span>(a.<span class="property">length</span> + b.<span class="property">length</span>);</span><br><span class="line">    res.<span class="title function_">set</span>(a);</span><br><span class="line">    res.<span class="title function_">set</span>(b, a.<span class="property">length</span>);</span><br><span class="line">    <span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">newMessage</span>(<span class="params"></span>): <span class="title class_">EventSourceMessage</span> &#123;</span><br><span class="line">    <span class="comment">// data, event, and id must be initialized to empty strings:</span></span><br><span class="line">    <span class="comment">// https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation</span></span><br><span class="line">    <span class="comment">// retry should be initialized to undefined so we return a consistent shape</span></span><br><span class="line">    <span class="comment">// to the js engine all the time: https://mathiasbynens.be/notes/shapes-ics#takeaways</span></span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">        <span class="attr">data</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">        <span class="attr">event</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">        <span class="attr">id</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">        <span class="attr">retry</span>: <span class="literal">undefined</span>,</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="keyword">enum</span> <span class="title class_">ControlChars</span> &#123;</span><br><span class="line">    <span class="title class_">NewLine</span> = <span class="number">10</span>,</span><br><span class="line">    <span class="title class_">CarriageReturn</span> = <span class="number">13</span>,</span><br><span class="line">    <span class="title class_">Space</span> = <span class="number">32</span>,</span><br><span class="line">    <span class="title class_">Colon</span> = <span class="number">58</span>,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Then there are several exposed functions, which we will use later in fetch.</p><p>The three functions cooperate with each other. getBytes is responsible for converting readablestream into bytes chunk, and getLines converts byte chunk into eventsource buffer, which is then converted by getMessage into data of type EventSourceMessage</p><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Converts a ReadableStream into a callback pattern.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> stream The input ReadableStream.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> onChunk A function that will be called on each new byte chunk in the stream.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@returns</span> &#123;<span class="type">Promise&lt;void&gt;</span>&#125; A promise that will be resolved when the stream closes.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">getBytes</span>(<span class="params"><span class="attr">stream</span>: <span class="title class_">ReadableStream</span>&lt;<span class="title class_">Uint8Array</span>&gt;, <span class="attr">onChunk</span>: (arr: <span class="built_in">Uint8Array</span>) =&gt; <span class="built_in">void</span></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> reader = stream.<span class="title function_">getReader</span>();</span><br><span class="line">    <span class="keyword">let</span> <span class="attr">result</span>: <span class="title class_">ReadableStreamDefaultReadResult</span>&lt;<span class="title class_">Uint8Array</span>&gt;;</span><br><span class="line">    <span class="keyword">while</span> (!(result = <span class="keyword">await</span> reader.<span class="title function_">read</span>()).<span class="property">done</span>) &#123;</span><br><span class="line">        <span class="title function_">onChunk</span>(result.<span class="property">value</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** </span></span><br><span class="line"><span class="comment"> * Parses arbitary byte chunks into EventSource line buffers.</span></span><br><span class="line"><span class="comment"> * Each line should be of the format &quot;field: value&quot; and ends with \r, \n, or \r\n. </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> onLine A function that will be called on each new EventSource line.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@returns</span> A function that should be called for each incoming byte chunk.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">getLines</span>(<span class="params"><span class="attr">onLine</span>: (line: <span class="built_in">Uint8Array</span>, fieldLength: <span class="built_in">number</span>) =&gt; <span class="built_in">void</span></span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> <span class="attr">buffer</span>: <span class="title class_">Uint8Array</span> | <span class="literal">undefined</span>;</span><br><span class="line">    <span class="keyword">let</span> <span class="attr">position</span>: <span class="built_in">number</span>; <span class="comment">// current read position</span></span><br><span class="line">    <span class="keyword">let</span> <span class="attr">fieldLength</span>: <span class="built_in">number</span>; <span class="comment">// length of the `field` portion of the line</span></span><br><span class="line">    <span class="keyword">let</span> discardTrailingNewline = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// return a function that can process each incoming byte chunk:</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">function</span> <span class="title function_">onChunk</span>(<span class="params"><span class="attr">arr</span>: <span class="title class_">Uint8Array</span></span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (buffer = <span class="literal">undefined</span>) &#123;</span><br><span class="line">            buffer = arr;</span><br><span class="line">            position = <span class="number">0</span>;</span><br><span class="line">            fieldLength = -<span class="number">1</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">// we&#x27;re still parsing the old line. Append the new bytes into buffer:</span></span><br><span class="line">            buffer = <span class="title function_">concat</span>(buffer, arr);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> bufLength = buffer.<span class="property">length</span>;</span><br><span class="line">        <span class="keyword">let</span> lineStart = <span class="number">0</span>; <span class="comment">// index where the current line starts</span></span><br><span class="line">        <span class="keyword">while</span> (position &lt; bufLength) &#123;</span><br><span class="line">            <span class="keyword">if</span> (discardTrailingNewline) &#123;</span><br><span class="line">                <span class="keyword">if</span> (buffer[position] = <span class="title class_">ControlChars</span>.<span class="property">NewLine</span>) &#123;</span><br><span class="line">                    lineStart = ++position; <span class="comment">// skip to next char</span></span><br><span class="line">                &#125;</span><br><span class="line">                </span><br><span class="line">                discardTrailingNewline = <span class="literal">false</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            </span><br><span class="line">            <span class="comment">// start looking forward till the end of line:</span></span><br><span class="line">            <span class="keyword">let</span> lineEnd = -<span class="number">1</span>; <span class="comment">// index of the \r or \n char</span></span><br><span class="line">            <span class="keyword">for</span> (; position &lt; bufLength &amp;&amp; lineEnd = -<span class="number">1</span>; ++position) &#123;</span><br><span class="line">                <span class="keyword">switch</span> (buffer[position]) &#123;</span><br><span class="line">                    <span class="keyword">case</span> <span class="title class_">ControlChars</span>.<span class="property">Colon</span>:</span><br><span class="line">                        <span class="keyword">if</span> (fieldLength = -<span class="number">1</span>) &#123; <span class="comment">// first colon in line</span></span><br><span class="line">                            fieldLength = position - lineStart;</span><br><span class="line">                        &#125;</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                    <span class="comment">// @ts-ignore:7029 \r case below should fallthrough to \n:</span></span><br><span class="line">                    <span class="keyword">case</span> <span class="title class_">ControlChars</span>.<span class="property">CarriageReturn</span>:</span><br><span class="line">                        discardTrailingNewline = <span class="literal">true</span>;</span><br><span class="line">                    <span class="keyword">case</span> <span class="title class_">ControlChars</span>.<span class="property">NewLine</span>:</span><br><span class="line">                        lineEnd = position;</span><br><span class="line">                        <span class="keyword">break</span>;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> (lineEnd = -<span class="number">1</span>) &#123;</span><br><span class="line">                <span class="comment">// We reached the end of the buffer but the line hasn&#x27;t ended.</span></span><br><span class="line">                <span class="comment">// Wait for the next arr and then continue parsing:</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="comment">// we&#x27;ve reached the line end, send it out:</span></span><br><span class="line">            <span class="title function_">onLine</span>(buffer.<span class="title function_">subarray</span>(lineStart, lineEnd), fieldLength);</span><br><span class="line">            lineStart = position; <span class="comment">// we&#x27;re now on the next line</span></span><br><span class="line">            fieldLength = -<span class="number">1</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (lineStart = bufLength) &#123;</span><br><span class="line">            buffer = <span class="literal">undefined</span>; <span class="comment">// we&#x27;ve finished reading it</span></span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (lineStart ! <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="comment">// Create a new view into buffer beginning at lineStart so we don&#x27;t</span></span><br><span class="line">            <span class="comment">// need to copy over the previous lines when we get the new arr:</span></span><br><span class="line">            buffer = buffer.<span class="title function_">subarray</span>(lineStart);</span><br><span class="line">            position -= lineStart;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/** </span></span><br><span class="line"><span class="comment"> * Parses line buffers into EventSourceMessages.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> onId A function that will be called on each `id` field.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> onRetry A function that will be called on each `retry` field.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> onMessage A function that will be called on each message.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@returns</span> A function that should be called for each incoming line buffer.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">getMessages</span>(<span class="params"></span></span><br><span class="line"><span class="params">    <span class="attr">onId</span>: (id: <span class="built_in">string</span>) =&gt; <span class="built_in">void</span>,</span></span><br><span class="line"><span class="params">    <span class="attr">onRetry</span>: (retry: <span class="built_in">number</span>) =&gt; <span class="built_in">void</span>,</span></span><br><span class="line"><span class="params">    <span class="attr">onMessage</span>?: (msg: EventSourceMessage) =&gt; <span class="built_in">void</span></span></span><br><span class="line"><span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> message = <span class="title function_">newMessage</span>();</span><br><span class="line">    <span class="keyword">const</span> decoder = <span class="keyword">new</span> <span class="title class_">TextDecoder</span>();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// return a function that can process each incoming line buffer:</span></span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">function</span> <span class="title function_">onLine</span>(<span class="params"><span class="attr">line</span>: <span class="title class_">Uint8Array</span>, <span class="attr">fieldLength</span>: <span class="built_in">number</span></span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (line.<span class="property">length</span> = <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="comment">// empty line denotes end of message. Trigger the callback and start a new message:</span></span><br><span class="line">            onMessage?.(message);</span><br><span class="line">            message = <span class="title function_">newMessage</span>();</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (fieldLength &gt; <span class="number">0</span>) &#123; <span class="comment">// exclude comments and lines with no values</span></span><br><span class="line">            <span class="comment">// line is of format &quot;&lt;field&gt;:&lt;value&gt;&quot; or &quot;&lt;field&gt;: &lt;value&gt;&quot;</span></span><br><span class="line">            <span class="comment">// https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation</span></span><br><span class="line">            <span class="keyword">const</span> field = decoder.<span class="title function_">decode</span>(line.<span class="title function_">subarray</span>(<span class="number">0</span>, fieldLength));</span><br><span class="line">            <span class="keyword">const</span> valueOffset = fieldLength + (line[fieldLength + <span class="number">1</span>] = <span class="title class_">ControlChars</span>.<span class="property">Space</span> ? <span class="number">2</span> : <span class="number">1</span>);</span><br><span class="line">            <span class="keyword">const</span> value = decoder.<span class="title function_">decode</span>(line.<span class="title function_">subarray</span>(valueOffset));</span><br><span class="line"></span><br><span class="line">            <span class="keyword">switch</span> (field) &#123;</span><br><span class="line">                <span class="keyword">case</span> <span class="string">&#x27;data&#x27;</span>:</span><br><span class="line">                    <span class="comment">// if this message already has data, append the new value to the old.</span></span><br><span class="line">                    <span class="comment">// otherwise, just set to the new value:</span></span><br><span class="line">                    message.<span class="property">data</span> = message.<span class="property">data</span></span><br><span class="line">                        ? message.<span class="property">data</span> + <span class="string">&#x27;\n&#x27;</span> + value</span><br><span class="line">                        : value; <span class="comment">// otherwise, </span></span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                <span class="keyword">case</span> <span class="string">&#x27;event&#x27;</span>:</span><br><span class="line">                    message.<span class="property">event</span> = value;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                <span class="keyword">case</span> <span class="string">&#x27;id&#x27;</span>:</span><br><span class="line">                    <span class="title function_">onId</span>(message.<span class="property">id</span> = value);</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">                <span class="keyword">case</span> <span class="string">&#x27;retry&#x27;</span>:</span><br><span class="line">                    <span class="keyword">const</span> retry = <span class="built_in">parseInt</span>(value, <span class="number">10</span>);</span><br><span class="line">                    <span class="keyword">if</span> (!<span class="built_in">isNaN</span>(retry)) &#123; <span class="comment">// per spec, ignore non-integers</span></span><br><span class="line">                        <span class="title function_">onRetry</span>(message.<span class="property">retry</span> = retry);</span><br><span class="line">                    &#125;</span><br><span class="line">                    <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Then there is the highlight, fetch.ts, in fact, the content of this file is relatively simple</p><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">EventSourceMessage</span>, getBytes, getLines, getMessages &#125; <span class="keyword">from</span> <span class="string">&#x27;./parse&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title class_">EventStreamContentType</span> = <span class="string">&#x27;text/event-stream&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title class_">DefaultRetryInterval</span> = <span class="number">1000</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="title class_">LastEventId</span> = <span class="string">&#x27;last-event-id&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">interface</span> <span class="title class_">FetchEventSourceInit</span> <span class="keyword">extends</span> <span class="title class_">RequestInit</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * The request headers. FetchEventSource only supports the Record&lt;string,string&gt; format.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="attr">headers</span>?: <span class="title class_">Record</span>&lt;<span class="built_in">string</span>, <span class="built_in">string</span>&gt;,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Called when a response is received. Use this to validate that the response</span></span><br><span class="line"><span class="comment">     * actually matches what you expect (and throw if it doesn&#x27;t.) If not provided,</span></span><br><span class="line"><span class="comment">     * will default to a basic validation to ensure the content-type is text/event-stream.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="attr">onopen</span>?: <span class="function">(<span class="params"><span class="attr">response</span>: <span class="title class_">Response</span></span>) =&gt;</span> <span class="title class_">Promise</span>&lt;<span class="built_in">void</span>&gt;,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Called when a message is received. <span class="doctag">NOTE:</span> Unlike the default browser</span></span><br><span class="line"><span class="comment">     * EventSource.onmessage, this callback is called for _all_ events,</span></span><br><span class="line"><span class="comment">     * even ones with a custom `event` field.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="attr">onmessage</span>?: <span class="function">(<span class="params"><span class="attr">ev</span>: <span class="title class_">EventSourceMessage</span></span>) =&gt;</span> <span class="built_in">void</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Called when a response finishes. If you don&#x27;t expect the server to kill</span></span><br><span class="line"><span class="comment">     * the connection, you can throw an exception here and retry using onerror.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="attr">onclose</span>?: <span class="function">() =&gt;</span> <span class="built_in">void</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Called when there is any error making the request / processing messages /</span></span><br><span class="line"><span class="comment">     * handling callbacks etc. Use this to control the retry strategy: if the</span></span><br><span class="line"><span class="comment">     * error is fatal, rethrow the error inside the callback to stop the entire</span></span><br><span class="line"><span class="comment">     * operation. Otherwise, you can return an interval (in milliseconds) after</span></span><br><span class="line"><span class="comment">     * which the request will automatically retry (with the last-event-id).</span></span><br><span class="line"><span class="comment">     * If this callback is not specified, or it returns undefined, fetchEventSource</span></span><br><span class="line"><span class="comment">     * will treat every error as retriable and will try again after 1 second.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="attr">onerror</span>?: <span class="function">(<span class="params"><span class="attr">err</span>: <span class="built_in">any</span></span>) =&gt;</span> <span class="built_in">number</span> | <span class="literal">null</span> | <span class="literal">undefined</span> | <span class="built_in">void</span>,</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * If true, will keep the request open even if the document is hidden.</span></span><br><span class="line"><span class="comment">     * By default, fetchEventSource will close the request and reopen it</span></span><br><span class="line"><span class="comment">     * automatically when the document becomes visible again.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="attr">openWhenHidden</span>?: <span class="built_in">boolean</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** The Fetch function to use. Defaults to window.fetch */</span></span><br><span class="line">    <span class="attr">fetch</span>?: <span class="keyword">typeof</span> fetch;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">fetchEventSource</span>(<span class="params"><span class="attr">input</span>: <span class="title class_">RequestInfo</span>, &#123;</span></span><br><span class="line"><span class="params">    signal: inputSignal,</span></span><br><span class="line"><span class="params">    headers: inputHeaders,</span></span><br><span class="line"><span class="params">    onopen: inputOnOpen,</span></span><br><span class="line"><span class="params">    onmessage,</span></span><br><span class="line"><span class="params">    onclose,</span></span><br><span class="line"><span class="params">    onerror,</span></span><br><span class="line"><span class="params">    openWhenHidden,</span></span><br><span class="line"><span class="params">    fetch: inputFetch,</span></span><br><span class="line"><span class="params">    ...rest</span></span><br><span class="line"><span class="params">&#125;: <span class="title class_">FetchEventSourceInit</span></span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>&lt;<span class="built_in">void</span>&gt;(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="comment">// make a copy of the input headers since we may modify it below:</span></span><br><span class="line">        <span class="keyword">const</span> headers = &#123; ...inputHeaders &#125;;</span><br><span class="line">        <span class="keyword">if</span> (!headers.<span class="property">accept</span>) &#123;</span><br><span class="line">            headers.<span class="property">accept</span> = <span class="title class_">EventStreamContentType</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">let</span> <span class="attr">curRequestController</span>: <span class="title class_">AbortController</span>;</span><br><span class="line">        <span class="keyword">function</span> <span class="title function_">onVisibilityChange</span>(<span class="params"></span>) &#123;</span><br><span class="line">            curRequestController.<span class="title function_">abort</span>(); <span class="comment">// close existing request on every visibility change</span></span><br><span class="line">            <span class="keyword">if</span> (!<span class="variable language_">document</span>.<span class="property">hidden</span>) &#123;</span><br><span class="line">                <span class="title function_">create</span>(); <span class="comment">// page is now visible again, recreate request.</span></span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (!openWhenHidden) &#123;</span><br><span class="line">            <span class="variable language_">document</span>.<span class="title function_">addEventListener</span>(<span class="string">&#x27;visibilitychange&#x27;</span>, onVisibilityChange);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">let</span> retryInterval = <span class="title class_">DefaultRetryInterval</span>;</span><br><span class="line">        <span class="keyword">let</span> retryTimer = <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">function</span> <span class="title function_">dispose</span>(<span class="params"></span>) &#123;</span><br><span class="line">            <span class="variable language_">document</span>.<span class="title function_">removeEventListener</span>(<span class="string">&#x27;visibilitychange&#x27;</span>, onVisibilityChange);</span><br><span class="line">            <span class="variable language_">window</span>.<span class="built_in">clearTimeout</span>(retryTimer);</span><br><span class="line">            curRequestController.<span class="title function_">abort</span>();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// if the incoming signal aborts, dispose resources and resolve:</span></span><br><span class="line">        inputSignal?.<span class="title function_">addEventListener</span>(<span class="string">&#x27;abort&#x27;</span>, <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="title function_">dispose</span>();</span><br><span class="line">            <span class="title function_">resolve</span>(); <span class="comment">// don&#x27;t waste time constructing/logging errors</span></span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> fetch = inputFetch ?? <span class="variable language_">window</span>.<span class="property">fetch</span>;</span><br><span class="line">        <span class="keyword">const</span> onopen = inputOnOpen ?? defaultOnOpen;</span><br><span class="line">        <span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">create</span>(<span class="params"></span>) &#123;</span><br><span class="line">            curRequestController = <span class="keyword">new</span> <span class="title class_">AbortController</span>();</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(input, &#123;</span><br><span class="line">                    ...rest,</span><br><span class="line">                    headers,</span><br><span class="line">                    <span class="attr">signal</span>: curRequestController.<span class="property">signal</span>,</span><br><span class="line">                &#125;);</span><br><span class="line"></span><br><span class="line">                <span class="keyword">await</span> <span class="title function_">onopen</span>(response);</span><br><span class="line">                </span><br><span class="line">                <span class="keyword">await</span> <span class="title function_">getBytes</span>(response.<span class="property">body</span>!, <span class="title function_">getLines</span>(<span class="title function_">getMessages</span>(<span class="function"><span class="params">id</span> =&gt;</span> &#123;</span><br><span class="line">                    <span class="keyword">if</span> (id) &#123;</span><br><span class="line">                        <span class="comment">// store the id and send it back on the next retry:</span></span><br><span class="line">                        headers[<span class="title class_">LastEventId</span>] = id;</span><br><span class="line">                    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                        <span class="comment">// don&#x27;t send the last-event-id header anymore:</span></span><br><span class="line">                        <span class="keyword">delete</span> headers[<span class="title class_">LastEventId</span>];</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;, <span class="function"><span class="params">retry</span> =&gt;</span> &#123;</span><br><span class="line">                    retryInterval = retry;</span><br><span class="line">                &#125;, onmessage)));</span><br><span class="line"></span><br><span class="line">                onclose?.();</span><br><span class="line">                <span class="title function_">dispose</span>();</span><br><span class="line">                <span class="title function_">resolve</span>();</span><br><span class="line">            &#125; <span class="keyword">catch</span> (err) &#123;</span><br><span class="line">                <span class="keyword">if</span> (!curRequestController.<span class="property">signal</span>.<span class="property">aborted</span>) &#123;</span><br><span class="line">                    <span class="comment">// if we haven&#x27;t aborted the request ourselves:</span></span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        <span class="comment">// check if we need to retry:</span></span><br><span class="line">                        <span class="keyword">const</span> <span class="attr">interval</span>: <span class="built_in">any</span> = onerror?.(err) ?? retryInterval;</span><br><span class="line">                        <span class="variable language_">window</span>.<span class="built_in">clearTimeout</span>(retryTimer);</span><br><span class="line">                        retryTimer = <span class="variable language_">window</span>.<span class="built_in">setTimeout</span>(create, interval);</span><br><span class="line">                    &#125; <span class="keyword">catch</span> (innerErr) &#123;</span><br><span class="line">                        <span class="comment">// we should not retry anymore:</span></span><br><span class="line">                        <span class="title function_">dispose</span>();</span><br><span class="line">                        <span class="title function_">reject</span>(innerErr);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="title function_">create</span>();</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">defaultOnOpen</span>(<span class="params"><span class="attr">response</span>: <span class="title class_">Response</span></span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> contentType = response.<span class="property">headers</span>.<span class="title function_">get</span>(<span class="string">&#x27;content-type&#x27;</span>);</span><br><span class="line">    <span class="keyword">if</span> (!contentType?.<span class="title function_">startsWith</span>(<span class="title class_">EventStreamContentType</span>)) &#123;</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(<span class="string">`Expected content-type to be <span class="subst">$&#123;EventStreamContentType&#125;</span>, Actual: <span class="subst">$&#123;contentType&#125;</span>`</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>This code has some other processing, such as automatic retry, such as closing the request when the page is inactive, and re-creating a new request when it re-enters the active state.</p><p>But the core function is to establish a connection through the fetch interface, and then continue to accept response.body through the getBytes method, and then continue to parse ByteFlow into the message form of EventSource through getLines and getMessage.</p><h1 id="principle"><a class="markdownIt-Anchor" href="#principle"></a> Principle</h1><p>This code looks very simple, but the question is, why can it be written like this, that is, there are two problems:</p><ul><li>Why fetch api can build links to SSE</li><li>Why can the response.body of the fetch api be continuously parsed, instead of the common form of a json object</li><li>Why getMessage can say line buffer parses correctly</li></ul><p>First of all, to put it simply, SSE is still based on HTTP in nature, so connections can be established through HTTP requests<br />Second, because the data format returned by our usual API interface is’application/json ‘, and the format returned by the sse interface is’text/event-stream’, response.body is actually a readableStream, so it can continuously transmit data back.<br />The third point, because this is stipulated in the agreement, according to the agreement, this is the agreement: <a href="https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation">https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation</a>, you can also see this article: <a href="https://www.cnblogs.com/goloving/p/9196066.html">https://www.cnblogs.com/goloving/p/9196066.html</a></p><p>Then there is a new question that can be raised here, why SSE returns can be a stream, that is, why HTTP can support stream output:</p><p>In fact, the answer is very simple: HTTP is already supported, but the common restful api we used before is a short connection. After obtaining the json data at one time, the connection is directly closed, which makes us forget that HTTP can support continuous return of data.</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;We all know that the interface of ChatGPT supports data return by streaming SSE, and the front-end browser provides EventSource by default to receive SSE, but the problem is that the default EventSource only supports Get requests, and does not support any custom headers. The interface of ChatGPT is a POST request, and it is necessary to carry a token in the header, so a Microsoft library is used. Let’s explain its usage, source code, and the basis for its source code to run from a protocol perspective, that is, why its source code can work&lt;/p&gt;</summary>
    
    
    
    <category term="Network" scheme="https://sunra.top/en/categories/Network/"/>
    
    
  </entry>
  
  <entry>
    <title>web instant messaging solution finishing</title>
    <link href="https://sunra.top/en/posts/60091/"/>
    <id>https://sunra.top/en/posts/60091/</id>
    <published>2023-04-08T01:35:32.000Z</published>
    <updated>2026-06-13T06:03:37.138Z</updated>
    
    <content type="html"><![CDATA[<p>Recently, I was curious about the protocol that chatgpt can return with streaming requests, so I went to learn about it. At first, I thought it was HTTP2, or the WS protocol, but later found out that it was not, but a protocol called SSE (Server-Sent Events).) protocol.</p><span id="more"></span><h1 id="instant-messaging-protocol-classification"><a class="markdownIt-Anchor" href="#instant-messaging-protocol-classification"></a> Instant messaging protocol classification</h1><h2 id="http-and-http2"><a class="markdownIt-Anchor" href="#http-and-http2"></a> HTTP and HTTP2</h2><p>HTTP protocol is our most common front-end and back-end instant messaging protocol, the more common is HTTP1, and later in order to solve some of its problems, we proposed HTTP2, but there is no particular change in nature.</p><p>Disadvantages of Http1</p><ul><li>Line head blocking: The method is that several requests are queued for serial single-threaded processing, and the latter requests wait for the return of the previous request to get the opportunity to execute. Once a certain request timed out, etc., the subsequent request can only be blocked, and there is no way., which is often called thread head blocking;</li><li>Insufficient use of TCP links: In HTTP 1.x, if you want to make multiple requests, you must use multiple TCP links, and the browser will limit 6-8 TCP link requests to a single domain name in order to control resources</li></ul><p>Advantages of HTTP2</p><ul><li>Multiple paths to reuse: The most valuable advantage solves the problem of thread head blocking, allows a single http2 connection to send multiple requests and responses, and makes full use of TCP. This makes resource sub-domain names, sprite maps, internal connection styles, etc. no longer applicable.</li><li>Header compression: HTTP2.0 can maintain static dictionaries and dynamic dictionaries on the client and server side to compress and differentially update HTTP headers, greatly reducing the traffic generated by header transmission. Headers in non-two dictionaries can be compressed using Huffman compression.</li><li>New binary format: http1.x is a text format transfer, http2 is a binary format transfer.</li><li>server level push: The server side can actively push resources to the Client.</li></ul><p>Here I will focus on this server level push. This push is different from websocket. Its server level push here means that the server level can actively push other resources when sending the HTML of the page, without waiting for the browser to parse to the corresponding location and initiate the request. For example, the server level can actively push JS and CSS files to the Client without the need for the Client to parse HTML and then send these requests.</p><p>The server level can actively push, and the Client also has the right to choose whether to receive it. If the resources pushed by the server level have been cached by the browser, the browser can reject them by sending RST_STREAM frames. Active push also abides by the same-origin policy, and the server will not casually push third-party resources to the Client.</p><h2 id="websocket"><a class="markdownIt-Anchor" href="#websocket"></a> WebSocket</h2><p>In the new generation of html standard html5, a network technology Websocket for full-duplex communication between browsers and servers is provided. From the Websocket draft, Websocket is a new and independent protocol, based on the TCP protocol, which is compatible with the http protocol, but will not be integrated into the http protocol, but only as part of html5. So the script is given another ability: to initiate websocket requests. We should be familiar with this method because Ajax does it this way, but the difference is that Ajax initiates http requests only.</p><p>Different from the request/response mode of the http protocol, Websocket has a Handshake (Opening Handshake) process before establishing a connection, and a Handshake (Closing Handshake) process before closing the connection. After establishing the connection, the two parties can communicate in both directions.</p><p>From the perspective of browser support, WebSocket is just around the corner, but there is still a long way to go, especially in China, a country where IE6, 7, and 8 are still prevalent. It will take a long time for the demise of old versions of browsers., Comet technology may still be the best solution before full browser compatibility is fully realized. However, there are currently some mature packaging solutions to solve this compatibility limitation</p><h2 id="sse"><a class="markdownIt-Anchor" href="#sse"></a> SSE</h2><p>SSE (Server-Sent Event) is an HTML5 technology that allows the server level to push new data to the client. This is a better solution than having the client pull new data from server level polling every few seconds.</p><p>Compared to WebSocket, it can also push data from the server level to the client. So how do you decide whether to use SSE or WebSocket? In general, what WebSocket can do, SSE can do, and vice versa, but they each have their own advantages in completing certain tasks.</p><p>WebSocket is a more complex server level implementation technology, but it is a true two-way transmission technology, which can push data from the server level to the client and from the client to the server level.</p><p>WebSocket and SSE have similar browser support rates, and most mainstream desktop browsers support both. In Android 4.3 and earlier, the system default browser does not support either, while Firefox and Chrome fully support both; in Android 4.4, the system default browser supports both; Safari supports SSE since 5.0 (iOS systems from 4.0), but does not properly support WebSocket until 6.0 (the WebSocket protocol implemented by Safari before 6.0 has security issues, so some mainstream browsers have disabled implementations based on this protocol).</p><p>Compared to WebSocket, SSE has some significant advantages. Personally, I think its biggest advantage is convenience: you don’t need to add any new components, and you can continue to use it in any backend language and framework you are used to. You don’t have to worry about creating a new virtual machine, getting a new IP or a new Port Number, it’s as simple as adding a new page to an existing website. I like to call this an existing infrastructure advantage.</p><p>The second advantage of SSE is the simplicity of the server. Relatively speaking, WebSocket is very complex and cannot be handled without the help of auxiliary class libraries.</p><p>Because SSE works on the existing HTTP/HTTPS protocol, it can run directly on existing proxy servers and authentication technologies. For WebSocket, proxy servers require some development (or other work) to support, and at the time of writing this book, many servers do not have it (although this situation will improve). SSE has another advantage: it is a text protocol, and script debugging is very easy.</p><p>However, this leads to a potential advantage of WebSocket over SSE: WebSocket is a binary protocol, while SSE is a text protocol (usually encoded in UTF-8). Of course, we can transfer binary data over an SSE connection: in SSE, there are only two characters with special meaning, CR and LF, and it is not difficult to transcode them. However, when transmitting binary data with SSE, the data will become larger. If you need to transfer a large amount of binary data from the server level to the Client, it is best to use WebSocket.</p><p>** The biggest advantage of WebSocket over SSE is that it is two-way communication, which means that sending data to the server level is as easy as receiving data from the server level. When using SSE, data is generally transmitted from the Client to the server level through a separate Ajax request. ** Compared to WebSocket, using Ajax in this way increases the overhead, but it is only a little more. As a result, the question becomes “When do you need to care about this difference?” If you need to transfer data to the server level at a frequency of 1 times per second or faster, you should use WebSocket. The frequency of 0.2 times per second to 1 time per second is a gray area, and there is little difference between using WebSocket and using SSE; but if you expect heavy loads, it is necessary to determine the reference point. When the frequency is lower than 0.2 times per second or so, there is little difference between the two.</p><p>What is the performance of transferring data from the server level to the Client? If it is text data instead of binary data (as mentioned earlier), there is no difference between SSE and WebSocket. They both use TCP/IP sockets and are both lightweight protocols. There is no difference in latency, bandwidth, server load, etc., unless… eh? Unless what?</p><p>When you take advantage of SSE’s existing infrastructure and set up a web server between client and server level scripts, the difference becomes apparent. An SSE connection not only uses a socket, but also takes up an Apache thread or process. If you use PHP, it will create a new PHP instance specifically for this connection. Apache and PHP use a lot of memory, which limits the number of parallel connections the server can support. Therefore, to achieve the same data transmission performance as WebSocket with SSE, you need to write your own backend server. Of course, those who will use their own server and use Node.js in any case will find this strange.</p><p>Let’s talk about the compatibility of WebSocket on older browsers. Currently, more than 2/3 of browsers support these new technologies, and the support rate of mobile end browsers will be lower. By convention, Flash is used whenever a two-way socket is needed, and backwards compatibility of WebSocket is usually done with Flash, which is quite complicated. If Flash is not available on the browser, the situation is even worse. In general, WebSocket is difficult to compatible, SSE is easy to compatible.</p><h1 id="instant-messaging-method-overview"><a class="markdownIt-Anchor" href="#instant-messaging-method-overview"></a> Instant messaging method overview</h1><p>In 1996, the IETF HTTP Working Group released version 1.0 of the HTTP protocol. Until version 1.1, which is commonly used now, the HTTP protocol has undergone 17 years of development. This distributed, stateless, TCP-based request/response protocol, which is widely used today when the Internet is prevalent, seems to have made slow progress compared to the rapid development of the Internet. From the rise of the Internet to the present, it has experienced the web1.0 era when portal websites were prevalent, and then with the emergence of ajax technology, it has developed into the web2.0 era when web applications were prevalent, and now it is moving towards web3.0. On the other hand, the development of the http protocol from version 1.0 to 1.1, in addition to default long connections, is a painless improvement in cache handling, bandwidth optimization, and security. It has always retained a stateless, request/response model, and never seems to realize that this should change.</p><p>Fortunately, the era of HTML5 has arrived, bringing WebSocket and SSE (Server-sent Events) to the realization of instant messages on the Web</p><h2 id="ajax-short-polling-script-sends-http-request"><a class="markdownIt-Anchor" href="#ajax-short-polling-script-sends-http-request"></a> Ajax short polling: script sends http request</h2><p>In order for a traditional web application to interact with a server, it must submit a form. The server receives and processes the incoming form, and then returns a brand new page. Because most of the data of the two pages before and after is the same, this process It transmits a lot of redundant data and wastes bandwidth. So Ajax technology came into being.</p><p>Ajax is short for Asynchronous JavaScript and XML, first proposed by Jesse James Garrett. This technology pioneered by allowing browser scripts (JS) to send http requests. Used by the Outlook Web Access team in 1998 and soon became part of IE4.0, but the technology remained niche until early 2005, when Google used it extensively in its goole groups, gmail and other interactive applications, making Ajax rapidly accepted by everyone.</p><p>The emergence of Ajax makes the transmission of data between the Client and the server much less and much faster, and also meets the needs of the initial development of the web2.0 era characterized by rich User Experience, but slowly it also exposes its drawbacks. For example, it cannot meet the requirements of real-time update data for rich interactive applications such as instant messaging. This browser-side technology is still based on the http protocol after all, and the request/response mode required by the http protocol cannot be changed unless the http protocol itself changes.</p><h2 id="comet-a-hack-technology-still-http-protocol"><a class="markdownIt-Anchor" href="#comet-a-hack-technology-still-http-protocol"></a> Comet: A Hack Technology (Still HTTP Protocol)</h2><p>The traditional polling-based method can no longer meet the low latency requirements of web applications represented by instant messaging, and it will also bring bad User Experience. So a “server push” technology based on http long connections was hacked. This technology was named Comet, a term first proposed by Alex Russell, project director of Dojo Toolkit, in the blog post Comet: Low Latency Data for the Browser, and has been used ever since.</p><p>In fact, server push has existed for a long time and is widely used in the classic client/server model. It’s just that browsers are too lazy and do not provide good support for this technology. But the advent of Ajax made it possible to implement this technology on browsers, and the integration of Google’s gmail and gtalk first used this technology. With the resolution of some key issues (such as the loading and display issues in IE), this technology was quickly recognized, and there are now many mature open source Comet frameworks.</p><p>The following is a comparison of typical Ajax and Comet data transmission methods. The difference is simple and clear. The typical Ajax communication method is also the classic use of the http protocol. To obtain data, you must first send a request. In web applications with high Low Latency requirements, the frequency of server requests can only be increased. Comet is different. The client maintains a long connection with the server, and only when the data required by the client is updated, the server actively pushes the data to the client.</p><p>There are two main ways to implement Comet, long-polling based on Ajax and http streaming based on Iframe and htmlfile.</p><h3 id="long-polling-based-on-ajax"><a class="markdownIt-Anchor" href="#long-polling-based-on-ajax"></a> Long polling based on Ajax</h3><p>The browser sends an XMLHttpRequest request. After receiving the request, the server side will block the request until there is data or timeout before returning it. The browser JS sends a request again after processing the request return information (timeout or valid data) to re-establish the connection. During this period, new data may have arrived on the server side, and the server will choose to save the data until the connection is re-established. The browser will retrieve all the data at once.</p><h3 id="streams-based-on-iframe-and-htmlfile"><a class="markdownIt-Anchor" href="#streams-based-on-iframe-and-htmlfile"></a> Streams based on Iframe and htmlfile</h3><p>Iframe is an html tag. The src attribute of this tag will keep the long connection request to the specified server, and the server can keep returning data. Compared with the first method, this method is closer to the traditional server push.</p><p>In the first way, the browser will call the JS callback function directly after receiving the data, but how to respond to the data in this way? You can embed a JS script in the returned data, such as’ &lt; script type = “text/javascript” &gt; js_func (“data from server”) </script > ', the server side will return the data as the parameter of the callback function, and the browser will execute this JS script after receiving the data.</p><h3 id="websocket-2"><a class="markdownIt-Anchor" href="#websocket-2"></a> WebSocket</h3><p>WebScoket is a new protocol and naturally a new solution</p><h3 id="sse-2"><a class="markdownIt-Anchor" href="#sse-2"></a> SSE</h3><p>SSE is a new protocol and naturally a new solution</p><h1 id="simple-principle-analysis-of-instant-message-scheme"><a class="markdownIt-Anchor" href="#simple-principle-analysis-of-instant-message-scheme"></a> Simple principle analysis of instant message scheme</h1><h2 id="communication-principles-of-traditional-web"><a class="markdownIt-Anchor" href="#communication-principles-of-traditional-web"></a> Communication Principles of Traditional Web</h2><p>The browser itself, as a thin Client, does not have the function of communicating directly with another Client browser in a remote place through system calls. This is different from the way our desktop applications work. Usually, desktop applications can establish a TCP connection with a process on the other end of the remote host through a socket, thus achieving full-duplex instant communication.</p><p>Since the birth of the browser, the client requests the server and the server returns the result, and there has been no change even though it has developed so far. So it is certain that in order to achieve communication between two clients, information must be forwarded through the server. For example, if A wants to communicate with B, A should first send the information to the IM application server, and the server forwards it to B according to the recipient carried in A’s information. Similarly, B to A is also in this mode.</p><h2 id="problems-that-need-to-be-solved-to-realize-im-application-in-traditional-communication-mode"><a class="markdownIt-Anchor" href="#problems-that-need-to-be-solved-to-realize-im-application-in-traditional-communication-mode"></a> Problems that need to be solved to realize IM application in traditional communication mode</h2><p>We recognize that implementing IM software based on the web still requires the browser to request the server model. In this way, the development of IM software needs to solve the following three problems:</p><ul><li>Duplex communication: that is, the browser pulls (pull) server data, and the server pushes (push) data to the browser;</li><li>Low latency: that is, the information sent by the browser A to B should be quickly forwarded to B through the server, and the information of B should also be quickly handed over to A, in fact, it requires any browser to quickly request the data of the server, and the server can Quickly push data to the browser;</li><li>Support cross-domain: Usually the Client browser and the server are in different locations of the network, the browser itself does not allow direct access to servers under different domain names through scripts, even if the IP Address is the same and the domain name is different, and the domain name is the same and the port is different. No, this is mainly for security reasons.</li></ul><h2 id="full-duplex-low-latency-solution"><a class="markdownIt-Anchor" href="#full-duplex-low-latency-solution"></a> Full duplex low latency solution</h2><h3 id="client-browser-short-polling"><a class="markdownIt-Anchor" href="#client-browser-short-polling"></a> Client browser short polling</h3><p>This is the simplest solution. The principle is that the Client sends a request to the server every short period of time through Ajax, the server returns the latest data, and then the Client updates the interface according to the obtained data, so that It indirectly realizes instant communication. The advantage is simplicity, but the disadvantage is that it puts a lot of pressure on the server and wastes bandwidth traffic (usually the data does not change).</p><h3 id="long-polling"><a class="markdownIt-Anchor" href="#long-polling"></a> Long polling</h3><p>In the above polling solution, since a request is sent every time, the server level sends the data regardless of whether the data changes or not, and the connection is closed after the request is completed. A lot of the communication passing through this is unnecessary, so there is a long-polling method. In this way, the client sends a request to the server, the server checks if the data requested by the client has changed (whether there is the latest data), and responds immediately if there is a change, otherwise the connection is maintained and the latest data is checked regularly until a data update or connection timeout occurs. At the same time, once the client connection is disconnected, the request is issued again, which greatly reduces the number of client requests to the server in the same time.</p><h3 id="based-on-http-stream-communication"><a class="markdownIt-Anchor" href="#based-on-http-stream-communication"></a> Based on http-stream communication</h3><p>There is also a communication method based on http-stream stream. The principle is to keep the client connected to the server level continuously during a request, and then the server level continuously transmits data to the client, just like the data stream, it does not send all the data to the client at once. The difference between it and the polling method is that the client only sends a request during the entire communication process, and then the server level maintains a long connection with the client, and uses this connection to send back data to the client.</p><p>This scheme is divided into several different data stream transmission methods.</p><h4 id="streaming-method-based-on-xhr-objects"><a class="markdownIt-Anchor" href="#streaming-method-based-on-xhr-objects"></a> Streaming method based on XHR objects</h4><p>The idea of this method is to construct an XHR object, by listening to its onreadystatechange event, when its readyState is 3, get its responseText and then process it. The readyState is 3, which means that the data transmission is in progress, and the entire communication process has not yet ended. So it is still getting the data sent by the server level. It means that the data is sent until the readyState is 4, and the communication process ends. In this process, the data passed by the server level to the client is sent to the Client in the form of stream multiple times, and the Client is also obtained in the form of stream, so it is called http-streaming data stream mode.</p><p>Here, since the data received by the Client is sent in segments, it is best to define a cursor received to obtain the latest data and discard the data that has been received before, and print out the latest data received each time through this cursor., and print out the entire responseText after the communication ends.</p><h4 id="based-on-iframe-data-stream"><a class="markdownIt-Anchor" href="#based-on-iframe-data-stream"></a> Based on iframe data stream</h4><p>Since earlier versions of IE do not allow the responseText property of XHR to be obtained when the readyState is 3, in order to achieve the use of this technology on IE, an iframe-based data stream communication method has emerged. Specifically, it is dynamically loading an iframe in the browser, so that its src attribute points to the URL of the requested server. In fact, it sends an http request to the server, and then creates a function for processing data on the browser side. At the server level, the data is output to the Client through the long connection between the iframe and the browser, but the returned data is not general data, but a function similar to ‘&lt; script type =\ &quot;text/javascript&quot; &gt; parent.process (’ “+ randomNum.toString ()+”')&lt;/ script &gt; 'The way the script is executed, the browser receives This data will be parsed into js code and find the specified function on the page to execute, in fact, the server level indirectly uses its own data to indirectly call the client’s code, to achieve the purpose of real-time update client.</p><h4 id="data-stream-communication-based-on-htmlfile"><a class="markdownIt-Anchor" href="#data-stream-communication-based-on-htmlfile"></a> Data stream communication based on htmlfile</h4><p>A new problem has arisen again. In IE, the iframe is used to request the server level. Before the server level keeps the communication connection and does not all return, the browser title has been loaded, and the bottom also shows that it is loading. This is for a product. User Experience is not good, so Google’s geniuses came up with a hack method. That is, in IE, dynamically generate an htmlfile object, which is a com component in the form of ActiveX. It is actually an HTML doc implemented in memory. By adding the generated iframe to the HTMLfile in this memory, and using the data flow of the iframe The communication method achieves the above effect. At the same time, because the HTMLfile object is not directly added to the page, it does not cause the browser to display the phenomenon of loading.</p><h4 id="sse-3"><a class="markdownIt-Anchor" href="#sse-3"></a> SSE</h4><p>In order to solve the problem that the browser can only unidirectional transmission of data to the server level, HTML5 provides a new technology called server push event SSE, which can realize the client request server level, and then the server level uses the communication connection established with the client to push data to the client, the client receives the data and processes it. From an independent point of view, SSE technology provides the function of pushing data from the server to the browser in one way, but with the active request of the browser, it actually realizes the two-way communication between the client and the server. Its principle is to construct an eventSource object in the Client, which has the readySate property, which is represented as follows:</p><p>0: Connecting to the server.<br />1: The connection is opened.<br />2: The connection is closed.</p><p>At the same time, the eventSource object will maintain a long connection with the server, and will be automatically reconnected after disconnection. If you want to force the connection, you can call its close method. It can listen to the onmessage event, the server level follows the format of SSE data transmission to the Client, and the Client can receive data when the onmessage event is triggered, so as to perform some processing</p><blockquote><p>Browser Native API</p></blockquote><h4 id="websocket-3"><a class="markdownIt-Anchor" href="#websocket-3"></a> WebSocket</h4><p>In the above solutions, they are all hack technologies formed by combining the browser’s one-way request to the server or the server’s one-way push of data to the browser. In HTML5, in order to enhance the functionality of the web, websocket technology is provided. It is not only a web communication method, but also an application layer protocol. It provides native dual full-duplex cross-domain communication between the browser and the server. Through the establishment of a websocket connection (actually a TCP connection) between the browser and the server, it can achieve Client-to-server and server-to-client data transmission at the same time. For the principle of this technology, please refer to: “WebSocket Detailed Explanation (1): Preliminary Understanding of WebSocket Technology”, “WebSocket Detailed Explanation (2): Technical Principle, Code Demonstration and Application Cases”, “WebSocket Detailed Explanation (3): In-depth WebSocket Communication Protocol Details”, I will not go into details here, and give the code directly. Before looking at the code, you need to understand the entire working process of websocket.</p><p>The first is Client new, a websocket object, which will send an http request to the server level. The server level finds that this is a webscoket request, and will agree to the protocol conversion and send back a response with a 101 status code to the Client. The above process is called a handshake. After this handshake, the Client establishes a TCP connection with the server level. On this connection, the server level and the Client can communicate in two directions. At this time, the two-way communication at the application layer is the ws or wss protocol, which has nothing to do with http. The so-called WS protocol requires the Client and server levels to send data messages network packets (frames) in a certain format before the other party can understand.</p><p>Reference article:<br /><a href="http://www.52im.net/thread-336-1-1.html">Web端即时通讯技术盘点：短轮询、Comet、Websocket、SSE</a><br /><a href="http://www.52im.net/thread-338-1-1.html">新手入门贴：史上最全Web端即时通讯技术原理详解</a></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;Recently, I was curious about the protocol that chatgpt can return with streaming requests, so I went to learn about it. At first, I thought it was HTTP2, or the WS protocol, but later found out that it was not, but a protocol called SSE (Server-Sent Events).) protocol.&lt;/p&gt;</summary>
    
    
    
    <category term="Sundry" scheme="https://sunra.top/en/categories/Sundry/"/>
    
    
  </entry>
  
  <entry>
    <title>Summary of GAMES101 Series (1) Linear Algebra and Model Transformation</title>
    <link href="https://sunra.top/en/posts/12801/"/>
    <id>https://sunra.top/en/posts/12801/</id>
    <published>2023-03-30T08:16:06.000Z</published>
    <updated>2026-06-13T06:03:37.123Z</updated>
    
    <content type="html"><![CDATA[<p>Recently, I began to re-learn the knowledge of Computer Graphics, so I set my eyes on GAMES101. While watching, I did it and summarized it. This time I summarize the basic knowledge of linear algebra and how to do model transformation in the game. Finally, finish homework 1.</p><span id="more"></span><h1 id="basic-knowledge-of-linear-algebra"><a class="markdownIt-Anchor" href="#basic-knowledge-of-linear-algebra"></a> Basic knowledge of linear algebra</h1><h2 id="vector"><a class="markdownIt-Anchor" href="#vector"></a> Vector</h2><ol><li>A vector is a line segment with a direction and a length, written in mathematical notation: $\ vec {a} $</li><li>Or expressed as a line segment from the beginning to the end, for example, there are two points A, B, then the vector from A to B can be expressed as $\ vec {AB} = B - A $</li><li>Vectors have no absolute starting point, that is, if a vector is moved in space, the vector itself remains unchanged</li><li>The length of the vector is expressed as: $| |\ vec {a} | | $, and the vector divided by its own length is the unit vector of changing direction: $\ frac {\ vec {a}} {| |\ vec {a} | |} $</li><li>The addition of vectors conforms to the parallelogram rule or the triangle rule</li></ol><h2 id="coordinates-can-be-represented-by-vectors"><a class="markdownIt-Anchor" href="#coordinates-can-be-represented-by-vectors"></a> Coordinates can be represented by vectors</h2><p>If there are two unit vectors perpendicular to each other, and we choose one of them to be $\ vec {X} $and the other to be $\ vec {Y} $, we can represent a vector $\ vec {A} =\ binom {x} {y} $, or $\ vec {A} ^ T = (x, y) $</p><p>We assume that the starting point of this vector is the origin, then the end point is the (x, y) point we usually say in geometry</p><h2 id="multiplication-of-a-vector"><a class="markdownIt-Anchor" href="#multiplication-of-a-vector"></a> Multiplication of a vector</h2><p>Vectors can be multiplied by dot. Suppose there are two vectors $\ vec {a},\ vec {b} $in different directions. Suppose their starting points are put together, and there will be an angle between them, assuming $\ theta $</p><p>那么 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mo>⋅</mo><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo>=</mo><mi mathvariant="normal">∣</mi><mi mathvariant="normal">∣</mi><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mi mathvariant="normal">∣</mi><mi mathvariant="normal">∣</mi><mi mathvariant="normal">∣</mi><mi mathvariant="normal">∣</mi><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mi mathvariant="normal">∣</mi><mi mathvariant="normal">∣</mi><mi>c</mi><mi>o</mi><mi>s</mi><mi>θ</mi></mrow><annotation encoding="application/x-tex">\vec{a} \cdot \vec{b} = ||\vec{a}||||\vec{b}||cos\theta</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.714em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.9774399999999999em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.2274399999999999em;vertical-align:-0.25em;"></span><span class="mord">∣</span><span class="mord">∣</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord">∣</span><span class="mord">∣</span><span class="mord">∣</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mord">∣</span><span class="mord">∣</span><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span></span></p><p>The point product of a vector has commutative and associative laws.</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mo>⋅</mo><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo>=</mo><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo>⋅</mo><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mspace linebreak="newline"></mspace><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mo>⋅</mo><mo stretchy="false">(</mo><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo>+</mo><mover accent="true"><mi>c</mi><mo>⃗</mo></mover><mo stretchy="false">)</mo><mo>=</mo><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mo>⋅</mo><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo>+</mo><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mo>⋅</mo><mover accent="true"><mi>c</mi><mo>⃗</mo></mover><mspace linebreak="newline"></mspace><mo stretchy="false">(</mo><mi>k</mi><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mo stretchy="false">)</mo><mo>⋅</mo><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo>=</mo><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mo>⋅</mo><mo stretchy="false">(</mo><mi>k</mi><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo stretchy="false">)</mo><mo>=</mo><mi>k</mi><mo stretchy="false">(</mo><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mo>⋅</mo><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\vec{a} \cdot \vec{b} = \vec{b} \cdot \vec{a} \\\vec{a} \cdot (\vec{b} + \vec{c}) = \vec{a} \cdot \vec{b} + \vec{a} \cdot \vec{c} \\(k\vec{a}) \cdot \vec{b} = \vec{a} \cdot (k\vec{b}) = k(\vec{a} \cdot \vec{b})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.714em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.9774399999999999em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.9774399999999999em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.714em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.714em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1.2274399999999999em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.17994em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.714em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1.0607699999999998em;vertical-align:-0.08333em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.714em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.714em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.17994em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.9774399999999999em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.714em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1.2274399999999999em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mopen">(</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1.2274399999999999em;vertical-align:-0.25em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p>The vector points are multiplied by coordinates:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext> </mtext><mi>v</mi><mi>e</mi><mi>c</mi><mi>a</mi><mtext> </mtext><mi>c</mi><mi>d</mi><mi>o</mi><mi>t</mi><mtext> </mtext><mi>v</mi><mi>e</mi><mi>c</mi><mi>b</mi><mo>=</mo><mtext> </mtext><mi>b</mi><mi>i</mi><mi>n</mi><mi>o</mi><mi>m</mi><msub><mi>x</mi><mi>a</mi></msub><msub><mi>y</mi><mi>a</mi></msub><mtext> </mtext><mi>c</mi><mi>d</mi><mi>o</mi><mi>t</mi><mtext> </mtext><mi>b</mi><mi>i</mi><mi>n</mi><mi>o</mi><mi>m</mi><msub><mi>x</mi><mi>b</mi></msub><msub><mi>y</mi><mi>b</mi></msub><mo>=</mo><msub><mi>x</mi><mi>a</mi></msub><msub><mi>x</mi><mi>b</mi></msub><mo>+</mo><msub><mi>y</mi><mi>a</mi></msub><msub><mi>y</mi><mi>b</mi></msub><mspace linebreak="newline"></mspace><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mo>⋅</mo><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>x</mi><mi>a</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>y</mi><mi>a</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>z</mi><mi>a</mi></msub></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo>⋅</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>x</mi><mi>b</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>y</mi><mi>b</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>z</mi><mi>b</mi></msub></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo>=</mo><msub><mi>x</mi><mi>a</mi></msub><msub><mi>y</mi><mi>a</mi></msub><mo>+</mo><msub><mi>x</mi><mi>b</mi></msub><msub><mi>y</mi><mi>b</mi></msub><mo>+</mo><msub><mi>z</mi><mi>a</mi></msub><msub><mi>z</mi><mi>b</mi></msub></mrow><annotation encoding="application/x-tex">\ vec {a}\ cdot\ vec {b} =\ binom {x _ a} {y _ a}\ cdot\ binom {x _ b} {y _ b} = x _ ax _ b + y _ ay _ b\\\vec{a} \cdot \vec{b} = \begin{bmatrix}    x_a \\ y_a \\ z_a\end{bmatrix} \cdot \begin{bmatrix}    x_b \\ y_b \\ z_b\end{bmatrix} = x_ay_a + x_by_b + z_az_b</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mspace"> </span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal">e</span><span class="mord mathnormal">c</span><span class="mord"><span class="mord mathnormal">a</span></span><span class="mspace"> </span><span class="mord mathnormal">c</span><span class="mord mathnormal">d</span><span class="mord mathnormal">o</span><span class="mord mathnormal">t</span><span class="mspace"> </span><span class="mord mathnormal" style="margin-right:0.03588em;">v</span><span class="mord mathnormal">e</span><span class="mord mathnormal">c</span><span class="mord"><span class="mord mathnormal">b</span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace"> </span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mord mathnormal">m</span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace"> </span><span class="mord mathnormal">c</span><span class="mord mathnormal">d</span><span class="mord mathnormal">o</span><span class="mord mathnormal">t</span><span class="mspace"> </span><span class="mord mathnormal">b</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal">o</span><span class="mord mathnormal">m</span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.73333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.714em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.9774399999999999em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:3.6010299999999997em;vertical-align:-1.55002em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.04398em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">⋅</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:3.6010299999999997em;vertical-align:-1.55002em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.04398em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.7777700000000001em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.7777700000000001em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.58056em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.04398em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.04398em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></p><p>Applications of vector dot multiplication are:</p><ul><li>We can use the result of the dot product between the two vectors and the 0 comparison to determine whether the angle between the two is acute or obtuse.</li><li>Find the angle between two vectors</li><li>Find the projection of one vector on another vector</li></ul><h2 id="cross-product-of-vectors"><a class="markdownIt-Anchor" href="#cross-product-of-vectors"></a> Cross product of vectors</h2><p>Another multiplication of vectors is cross multiplication</p><p>The direction of the cross product of the vector follows the right-hand rule. Assuming $\ vec {a}\ times\ vec {b} $, then the direction of the result is that the four fingers of the right hand turn from the direction of the vector a to the direction of b, clench tightly, and then give a thumbs up is, the direction of the thumb. That is, the result of the cross product is perpendicular to the plane where a and b are located</p><p>Then the length of the cross product is actually $|\ vec {a}\ times\ vec {b }||=||\ vec {a} | | | |\ vec {b} | | sin\ theta $</p><p>The cross product of vectors does not support associativity. To be precise, the result of the order of commutative cross products is reversed, that is, the direction is reversed: $\ vec {a}\ times\ vec {b} = -\ vec {b}\ times\ vec {a} $</p><p>The cross product of the vector is represented by a matrix:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mo>×</mo><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msub><mi>y</mi><mi>a</mi></msub><msub><mi>z</mi><mi>b</mi></msub><mo>−</mo><msub><mi>y</mi><mi>b</mi></msub><msub><mi>z</mi><mi>a</mi></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msub><mi>x</mi><mi>a</mi></msub><msub><mi>z</mi><mi>b</mi></msub><mo>−</mo><msub><mi>x</mi><mi>b</mi></msub><msub><mi>z</mi><mi>a</mi></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msub><mi>x</mi><mi>a</mi></msub><msub><mi>y</mi><mi>b</mi></msub><mo>−</mo><msub><mi>x</mi><mi>b</mi></msub><msub><mi>y</mi><mi>a</mi></msub></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mspace linebreak="newline"></mspace><mover accent="true"><mi>a</mi><mo>⃗</mo></mover><mo>×</mo><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo>=</mo><mi>A</mi><mo>∗</mo><mover accent="true"><mi>b</mi><mo>⃗</mo></mover><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><msub><mi>z</mi><mi>a</mi></msub></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>y</mi><mi>a</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>z</mi><mi>a</mi></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><msub><mi>x</mi><mi>a</mi></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><msub><mi>y</mi><mi>a</mi></msub></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>x</mi><mi>a</mi></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>x</mi><mi>b</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>y</mi><mi>b</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>z</mi><mi>b</mi></msub></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">\vec{a} \times \vec{b} = \begin{bmatrix}    y_az_b - y_bz_a \\    x_az_b - x_bz_a \\    x_ay_b - x_by_a\end{bmatrix} \\\vec{a} \times \vec{b} = A * \vec{b} = \begin{bmatrix}    0 &amp; -z_a &amp; y_a \\    z_a &amp; 0 &amp; -x_a \\    -y_a &amp; x_a &amp; 0 \\\end{bmatrix} \begin{bmatrix}    x_b \\ y_b \\ z_b\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.79733em;vertical-align:-0.08333em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.9774399999999999em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:3.6010299999999997em;vertical-align:-1.55002em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.04398em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.04398em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.04398em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.04398em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.79733em;vertical-align:-0.08333em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.9774399999999999em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal">A</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.9774399999999999em;vertical-align:0em;"></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9774399999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.26344em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:3.6010299999999997em;vertical-align:-1.55002em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.04398em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.04398em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">a</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.33610799999999996em;"><span style="top:-2.5500000000000003em;margin-left:-0.04398em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">b</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>Cross product can determine whether a vector is on the left or right of another vector. This is easier to understand. When the right-hand rule rotates, it rotates clockwise or counterclockwise, and the result is the opposite.</p><p>Another function is to determine whether a point is inside a triangle</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680175423/origin-of-ray/screenshot-20230330-192228_m9tuer.png" alt="" /></p><p>In the figure above, if the symbols of vector BC cross-multiplied by vector BP, vector CA cross-multiplied by vector CP, and vector AB cross-multiplied by vector AP are all the same, then it means that the P point is inside</p><h2 id="matrix"><a class="markdownIt-Anchor" href="#matrix"></a> Matrix</h2><p>A matrix is a two-dimensional array of m rows and n columns.</p><p>The premise that two matrices can be multiplied is that the number of columns in the first matrix and the number of rows in the second matrix are the same.</p><p>That is, a matrix with M rows and N columns can be multiplied by a matrix with N rows and P columns, resulting in a matrix with M rows and P columns.</p><p>Suppose A and B are multiplied by two matrices to a matrix C, where each term of A is $a_ {ij} $, each term of B is $B_ {ij} $, and each term of C is $c_ {ij} $, then $c_ {ij} =\ sum_ {k = 0} ^ {k = N} a_ {ik} b_ {kj} $</p><p>The important point here is how to write the equations of coordinate transformation in the form of matrices</p><p>For example, how to say that points in a two-dimensional coordinate system are symmetrical according to the y-axis</p><p>Just write it in a system of equations</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo fence="true">{</mo><mtable rowspacing="0.3599999999999999em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msup><mi>x</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>=</mo><mo>−</mo><mi>x</mi><mo separator="true">;</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msup><mi>y</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>=</mo><mi>y</mi></mrow></mstyle></mtd></mtr></mtable></mrow><annotation encoding="application/x-tex">\begin{cases}    x&#x27; = -x; \\    y&#x27; = y\end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.0000299999999998em;vertical-align:-1.25003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord">−</span><span class="mord mathnormal">x</span><span class="mpunct">;</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>Write it in matrix form</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mn>1</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>x</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>y</mi></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mi>x</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>y</mi></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">\begin{bmatrix}    -1 &amp; 0 \\    0 &amp; 1\end{bmatrix}\begin{bmatrix}    x \\ y\end{bmatrix} = \begin{bmatrix}    -x \\ y\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.40003em;vertical-align:-0.95003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord">1</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:2.40003em;vertical-align:-0.95003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord mathnormal">x</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span></span></span></span></span></p><p>Each matrix has its own transpose matrix and inverse matrix.</p><p>The transpose matrix of A is written as $A_T $, and $ (AB) ^ T = B ^ TA ^ T $</p><p>The Inverse Matrix of A is written as $A ^ {-1} $, and $AA ^ {-1} = I $, where I is the identity matrix, and any matrix multiplied by the identity matrix equals nothing, that is, any matrix multiplied by A The change produced by the matrix can be restored by multiplying the Inverse Matrix of A</p><h1 id="how-to-use-a-matrix-to-transform-transform"><a class="markdownIt-Anchor" href="#how-to-use-a-matrix-to-transform-transform"></a> How to use a matrix to transform (Transform)</h1><h2 id="2d-transformation"><a class="markdownIt-Anchor" href="#2d-transformation"></a> 2D transformation</h2><ol><li>Zoom out</li></ol><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680229930/origin-of-ray/WX20230331-102939_2x_ch8yoi.png" alt="" /></p><p>When the image is scaled by s times, it is represented by the equation</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo fence="true">{</mo><mtable rowspacing="0.3599999999999999em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msup><mi>x</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>=</mo><mi>s</mi><mi>x</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msup><mi>y</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>=</mo><mi>s</mi><mi>y</mi></mrow></mstyle></mtd></mtr></mtable></mrow><annotation encoding="application/x-tex">\begin{cases}x&#x27; = sx \\y&#x27; = sy \\\end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.0000299999999998em;vertical-align:-1.25003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">x</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>The corresponding scaling matrix is:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>s</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>s</mi></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><annotation encoding="application/x-tex">\begin{bmatrix}s &amp; 0 \\0 &amp; s\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.40003em;vertical-align:-0.95003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">s</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">s</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span></span></span></span></span></p><ol start="2"><li>Inversion</li></ol><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680229931/origin-of-ray/WX20230331-103001_2x_npdyxc.png" alt="" /></p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mn>1</mn></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><annotation encoding="application/x-tex">\begin{bmatrix}-1 &amp; 0 \\0 &amp; 1 \\\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.40003em;vertical-align:-0.95003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord">1</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span></span></span></span></span></p><ol start="3"><li>Shear</li></ol><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680229930/origin-of-ray/WX20230331-103010_2x_h48ruq.png" alt="" /></p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>a</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><annotation encoding="application/x-tex">\begin{bmatrix}1 &amp; a \\0 &amp; 1\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.40003em;vertical-align:-0.95003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span></span></span></span></span></p><p>Step 4 Rotate</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680229931/origin-of-ray/WX20230331-103029_2x_khbazr.png" alt="" /></p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>c</mi><mi>o</mi><mi>s</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mi>s</mi><mi>i</mi><mi>n</mi><mi>θ</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>s</mi><mi>i</mi><mi>n</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>c</mi><mi>o</mi><mi>s</mi><mi>θ</mi></mrow></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><annotation encoding="application/x-tex">\begin{bmatrix}cos\theta &amp; -sin\theta \\sin\theta &amp; cos\theta\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.40003em;vertical-align:-0.95003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span></span></span></span></span></p><p>So far, all our transformations can be expressed in matrix form, because our previous transformations can be expressed in the following equation:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo fence="true">{</mo><mtable rowspacing="0.3599999999999999em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msup><mi>x</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>=</mo><mi>a</mi><mi>x</mi><mo>+</mo><mi>b</mi><mi>y</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msup><mi>y</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>=</mo><mi>c</mi><mi>x</mi><mo>+</mo><mi>d</mi><mi>y</mi></mrow></mstyle></mtd></mtr></mtable></mrow><annotation encoding="application/x-tex">\begin{cases}x&#x27; = ax + by \\y &#x27;= cx + dy\end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.0000299999999998em;vertical-align:-1.25003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord mathnormal">a</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord mathnormal">b</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord mathnormal">c</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord mathnormal">d</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>Expressed as a matrix is</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msup><mi>x</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msup><mi>y</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>a</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>b</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>c</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>d</mi></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>x</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>y</mi></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">\begin{bmatrix}x&#x27; \\ y&#x27;\end{bmatrix}=\begin{bmatrix}a &amp; b \\c &amp; d \\\end{bmatrix}\begin{bmatrix}x \\ y\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.40003em;vertical-align:-0.95003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:2.40003em;vertical-align:-0.95003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">d</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span></span></span></span></span></p><p>But the problem is that you can’t represent translation in this way, because translation can’t be written in this form</p><ol start="5"><li>Translation</li></ol><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680229931/origin-of-ray/WX20230331-103041_2x_cdpzl7.png" alt="" /></p><p>The system of equations for translation is like this:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo fence="true">{</mo><mtable rowspacing="0.3599999999999999em" columnalign="left left" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msup><mi>x</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>=</mo><mi>x</mi><mo>+</mo><msub><mi>t</mi><mi>x</mi></msub><mo separator="true">;</mo></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><msup><mi>y</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>=</mo><mi>y</mi><mo>+</mo><msub><mi>t</mi><mi>y</mi></msub><mo separator="true">;</mo></mrow></mstyle></mtd></mtr></mtable></mrow><annotation encoding="application/x-tex">\begin{cases}x&#x27; = x + t_x;\\y&#x27; = y + t_y;\end{cases}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.0000299999999998em;vertical-align:-1.25003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size4">{</span></span><span class="mord"><span class="mtable"><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.69em;"><span style="top:-3.69em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">;</span></span></span><span style="top:-2.25em;"><span class="pstrut" style="height:3.008em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mpunct">;</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.19em;"><span></span></span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>If scaling, rotation, and translation are all represented by matrices, they should be as follows:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msup><mi>x</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msup><mi>y</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>a</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>b</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>c</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>d</mi></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>x</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>y</mi></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo>+</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>x</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>y</mi></msub></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">\begin{bmatrix}x&#x27; \\ y&#x27;\end{bmatrix}=\begin{bmatrix}a &amp; b \\c &amp; d \end{bmatrix}\begin{bmatrix}x \\ y\end{bmatrix}+\begin{bmatrix}t_x \\ t_y\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.40003em;vertical-align:-0.95003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:2.40003em;vertical-align:-0.95003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">d</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:2.40003em;vertical-align:-0.95003em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;"><span class="delimsizing size3">[</span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.45em;"><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.9500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;"><span class="delimsizing size3">]</span></span></span></span></span></span></span></p><p>So at this time we have to introduce homogeneous coordinates, that is, add w. At this time, the 2D point coordinates are represented by (x, y, 1), and the 2D vector is represented by (x, y, 0)</p><p>When representing a point, w is 1, when representing a vector, w is 0, and there is a very magical place like this, that is, if two points are subtracted, w will become 0, which happens to be a vector, point and vector Adding, w is 1, which is also a point</p><p>Using homogeneous coordinates, we can uniformly rotate, scale, and translate into a matrix</p><p>The translation is expressed in homogeneous coordinates as:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msup><mi>x</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msup><mi>y</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msup><mi>z</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>x</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>y</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>x</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>y</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>x</mi><mo>+</mo><msub><mi>t</mi><mi>x</mi></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>y</mi><mo>+</mo><msub><mi>t</mi><mi>y</mi></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">\begin{bmatrix}x&#x27; \\ y&#x27; \\ z&#x27;\end{bmatrix}=\begin{bmatrix}1 &amp; 0 &amp; t_x \\0 &amp; 1 &amp; t_y \\0 &amp; 0 &amp; 1 \\\end{bmatrix}\begin{bmatrix}x \\ y \\ 1\end{bmatrix}=\begin{bmatrix}x + t_x \\y + t_y \\1\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.6010299999999997em;vertical-align:-1.55002em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:3.6010299999999997em;vertical-align:-1.55002em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:3.6010299999999997em;vertical-align:-1.55002em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><ol start="6"><li>Mixing</li></ol><p>We can now use homogeneous coordinates to represent rotation, translation, and scaling respectively</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>S</mi><mo stretchy="false">(</mo><msub><mi>s</mi><mi>x</mi></msub><mo separator="true">,</mo><msub><mi>s</mi><mi>y</mi></msub><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>s</mi><mi>x</mi></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>s</mi><mi>y</mi></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mspace linebreak="newline"></mspace><mi>R</mi><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>c</mi><mi>o</mi><mi>s</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mi>s</mi><mi>i</mi><mi>n</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>s</mi><mi>i</mi><mi>n</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>c</mi><mi>o</mi><mi>s</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mspace linebreak="newline"></mspace><mi>T</mi><mo stretchy="false">(</mo><msub><mi>t</mi><mi>x</mi></msub><mo separator="true">,</mo><msub><mi>t</mi><mi>y</mi></msub><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>x</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>y</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">S(s_x, s_y) = \begin{bmatrix}s_x &amp; 0 &amp; 0 \\0 &amp; s_y &amp; 0 \\0 &amp; 0 &amp; 1\end{bmatrix}\\R(\theta) = \begin{matrix}cos\theta &amp; -sin\theta &amp; 0 \\sin\theta &amp; cos\theta &amp; 0 \\0 &amp; 0 &amp; 1\end{matrix}\\T(t_x, t_y) = \begin{bmatrix}1 &amp; 0 &amp; t_x \\0 &amp; 1 &amp; t_y \\0 &amp; 0 &amp; 1\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.036108em;vertical-align:-0.286108em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:3.6010299999999997em;vertical-align:-1.55002em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:3.6000000000000005em;vertical-align:-1.5500000000000007em;"></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1.036108em;vertical-align:-0.286108em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:3.6010299999999997em;vertical-align:-1.55002em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>So how do we mix these operations?</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680229930/origin-of-ray/WX20230331-103100_2x_f3wqos.png" alt="" /></p><p>As you can see in the figure above, we now translate and then rotate. The result of translation is different from that of rotation first, because our rotation matrix is rotated around the origin</p><p>Therefore, we generally specify the order to perform mixing operations. The first operation is multiplied left by the coordinates of the current point, and after obtaining the new point, it is multiplied left by the next operation matrix.</p><p>Then, although our order cannot be changed because matrix multiplication has no commutativity, matrix multiplication has associativity, that is:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680235553/origin-of-ray/WX20230331-120541_2x_tdldry.png" alt="" /></p><p>So we can achieve the result of multiplying the rotation, scaling, and translation matrices as the transformation matrix, and then multiplying it left with each point</p><p>There is actually another problem here, which is, what if we just want a point to rotate around its lower left corner?</p><p>It’s simple, translate the bottom left corner to the origin, then rotate, and finally translate the bottom left corner back:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680235680/origin-of-ray/WX20230331-120741_2x_owrzbw.png" alt="" /></p><h2 id="3d-transformation"><a class="markdownIt-Anchor" href="#3d-transformation"></a> 3D transformation</h2><p>The transformation of 3D is actually no different from 2D, except that homogeneous coordinates have four dimensions</p><p>The transformation matrix is as follows:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msup><mi>x</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msup><mi>y</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msup><mi>z</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>a</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>b</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>c</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>x</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>d</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>e</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>f</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>y</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>g</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>h</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>o</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>z</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>x</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>y</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>z</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">\begin{bmatrix}x&#x27; \\ y&#x27; \\ z&#x27; \\ 1\end{bmatrix}=\begin{bmatrix}a &amp; b &amp; c &amp; t_x \\d &amp; e &amp; f &amp; t_y \\g &amp; h &amp; o &amp; t_z \\0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix}\begin{bmatrix}x \\ y \\ z \\ 1\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.80303em;vertical-align:-2.15003em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.751892em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:4.80303em;vertical-align:-2.15003em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">d</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">b</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">e</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">h</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">o</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.04398em;">z</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>The scaling matrix can be written as;</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>S</mi><mo stretchy="false">(</mo><msub><mi>s</mi><mi>x</mi></msub><mo separator="true">,</mo><msub><mi>s</mi><mi>y</mi></msub><mo separator="true">,</mo><msub><mi>s</mi><mi>z</mi></msub><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>s</mi><mi>x</mi></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>x</mi><mi>y</mi></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>s</mi><mi>z</mi></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">S(s_x, s_y, s_z) = \begin{bmatrix}s_x &amp; 0 &amp; 0 &amp; 0\\0 &amp; x_y &amp; 0 &amp; 0\\0 &amp; 0 &amp; s_z &amp; 0 \\0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.036108em;vertical-align:-0.286108em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.04398em;">z</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:4.80303em;vertical-align:-2.15003em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.04398em;">z</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>The translation matrix can be expressed as:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>T</mi><mo stretchy="false">(</mo><msub><mi>t</mi><mi>x</mi></msub><mo separator="true">,</mo><msub><mi>t</mi><mi>y</mi></msub><mo separator="true">,</mo><msub><mi>t</mi><mi>z</mi></msub><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>x</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>y</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>t</mi><mi>z</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">T(t_x, t_y, t_z) = \begin{bmatrix}1 &amp; 0 &amp; 0 &amp; t_x \\0 &amp; 1 &amp; 0 &amp; t_y \\0 &amp; 0 &amp; 1 &amp; t_z \\0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.036108em;vertical-align:-0.286108em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.04398em;">z</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:4.80303em;vertical-align:-2.15003em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">t</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.04398em;">z</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>Rotation is more complicated because it can be divided into rotation around different axes</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>R</mi><mi>x</mi></msub><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>c</mi><mi>o</mi><mi>s</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mi>s</mi><mi>i</mi><mi>n</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>s</mi><mi>i</mi><mi>n</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>c</mi><mi>o</mi><mi>s</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mspace linebreak="newline"></mspace><msub><mi>R</mi><mi>y</mi></msub><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>c</mi><mi>o</mi><mi>s</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>s</mi><mi>i</mi><mi>n</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>s</mi><mi>i</mi><mi>n</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>c</mi><mi>o</mi><mi>s</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mspace linebreak="newline"></mspace><msub><mi>R</mi><mi>z</mi></msub><mo stretchy="false">(</mo><mi>θ</mi><mo stretchy="false">)</mo><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>c</mi><mi>o</mi><mi>s</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><mi>s</mi><mi>i</mi><mi>n</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>s</mi><mi>i</mi><mi>n</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>c</mi><mi>o</mi><mi>s</mi><mi>θ</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">R_x(\theta) = \begin{bmatrix}1 &amp; 0 &amp; 0 &amp; 0 \\0 &amp; cos\theta &amp; -sin\theta &amp; 0 \\0 &amp; sin\theta &amp; cos\theta &amp; 0 \\0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix} \\R_y(\theta) = \begin{bmatrix}cos\theta &amp; 0 &amp; sin\theta &amp; 0 \\0 &amp; 1 &amp; 0 &amp; 0 \\sin\theta &amp; 0 &amp; cos\theta &amp; 0 \\0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix} \\R_z(\theta) = \begin{bmatrix}cos\theta &amp; -sin\theta &amp; 0 &amp; 0 \\sin\theta &amp; cos\theta &amp; 0 &amp; 0 \\0 &amp; 0 &amp; 1 &amp; 0 \\0 &amp; 0 &amp; 0 &amp; 1\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.00773em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:4.80303em;vertical-align:-2.15003em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1.036108em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:-0.00773em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:4.80303em;vertical-align:-2.15003em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.00773em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.04398em;">z</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:4.80303em;vertical-align:-2.15003em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.02778em;">θ</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>There is also a formula to multiply any rotation matrix Factorization by the rotation matrix in three axis directions. The following way represents the rotation angle of $\ theta $around the $\ vec {n} $axis.</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>R</mi><mo stretchy="false">(</mo><mover accent="true"><mi>n</mi><mo>⃗</mo></mover><mo separator="true">,</mo><mi>α</mi><mo stretchy="false">)</mo><mo>=</mo><mi>c</mi><mi>o</mi><mi>s</mi><mi>α</mi><mover accent="true"><mi>I</mi><mo>⃗</mo></mover><mo>+</mo><mo stretchy="false">(</mo><mn>1</mn><mo>−</mo><mi>c</mi><mi>o</mi><mi>s</mi><mi>α</mi><mo stretchy="false">)</mo><mover accent="true"><mi>n</mi><mo>⃗</mo></mover><msup><mover accent="true"><mi>n</mi><mo>⃗</mo></mover><mi>T</mi></msup><mo>+</mo><mi>s</mi><mi>i</mi><mi>n</mi><mi>α</mi><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><msub><mi>n</mi><mi>z</mi></msub></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>n</mi><mi>y</mi></msub></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>n</mi><mi>z</mi></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><msub><mi>n</mi><mi>x</mi></msub></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mo>−</mo><msub><mi>n</mi><mi>y</mi></msub></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><msub><mi>n</mi><mi>x</mi></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">R(\vec{n}, \alpha) = cos\alpha\vec{I} + (1 - cos\alpha)\vec{n}\vec{n}^T + sin\alpha\begin{bmatrix}0 &amp; -n_z &amp; n_y \\n_z &amp; 0 &amp; -n_x \\-n_y &amp; n_x &amp; 0 \\\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.00773em;">R</span><span class="mopen">(</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.0496599999999998em;vertical-align:-0.08333em;"></span><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9663299999999999em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">I</span></span></span><span style="top:-3.25233em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.12438999999999999em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1.1413309999999999em;vertical-align:-0.25em;"></span><span class="mord mathnormal">c</span><span class="mord mathnormal">o</span><span class="mord mathnormal">s</span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mclose">)</span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="mord"><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.714em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="accent-body" style="left:-0.2355em;"><span class="overlay" style="height:0.714em;width:0.471em;"><svg width='0.471em' height='0.714em' style='width:0.471em' viewBox='0 0 471 714' preserveAspectRatio='xMinYMin'><path d='M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 53.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 1110.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359c-16-25.333-24-45-24-59z'/></svg></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913309999999999em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:3.6010299999999997em;vertical-align:-1.55002em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.0037em;">α</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.04398em;">z</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.04398em;">z</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.15139200000000003em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">y</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">−</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">x</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><h1 id="observation-transformation-in-graphics"><a class="markdownIt-Anchor" href="#observation-transformation-in-graphics"></a> Observation Transformation in Graphics</h1><p>When we are doing game development and writing Shader, we often use something called an MVP matrix to change the coordinates of points on the model to the coordinates on the screen.</p><p>The MVP here refers to Model, View, and Projection, which means model transformation, view transformation, and projection transformation</p><p>Model transformation is to change the coordinates from the coordinate system of the model itself to the coordinates of the game world coordinate system</p><p>View transformation is to change the coordinates on the world coordinate system into the coordinates of the observation space</p><p>The projection transformation is to change the coordinates of the observation space into the clipping space. In fact, this step does not do the operation of projecting to the two-dimensional plane. The specific projection operation is written in the GPU in the rendering pipeline, and is generally not processed in the Shader.</p><p>The observation transformation we are talking about here is just a step in the rendering pipeline. At the beginning, it is operated vertex-by-vertex in the vertex shader. We get the coordinates of the point in the clipping space. In the next rendering pipeline, we have to go through grating., sampling, chip-by-chip shader output color, depth test, etc. will finally be projected onto a two-dimensional plane.</p><p>Tired than the usual way we take pictures, the Model matrix is like we find a suitable camera position, the View matrix is to use the camera to find an angle</p><p>We don’t talk about the Model matrix here, because it is the same as the View matrix, which changes from one coordinate system to another, and the Projection matrix is different in that the observation space is a box with a side length of 1 cube, we need to consider scaling</p><h2 id="view-matrix"><a class="markdownIt-Anchor" href="#view-matrix"></a> View matrix</h2><p>View matrix is the point from the world coordinates into the observation space, i.e., from the origin of the world coordinate system relative to the camera position becomes coordinates.</p><p>After the Model transformation, we have the coordinates of the point in space, now we need to define the position and orientation of the camera in space:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680243906/origin-of-ray/WX20230331-142433_2x_an1pc4.png" alt="" /></p><p>The coordinates and orientation of the camera here are relative to the world coordinate system. And our object coordinates are currently relative to the world coordinate system.</p><p>Now all we have to do is change the object coordinates relative to the world coordinate system to relative to the camera coordinates.</p><p>Here we introduce a common physical concept - relative motion, that is, if the same transformation operation is performed on the camera and the object, the relative position of the two remains unchanged.</p><p>Then we can now try to move the camera to the origin. The observation direction of the camera is towards the negative direction of the z-axis of the world coordinate system, find the matrix of this transformation, and then apply this matrix to each point, which is equivalent to moving the object to the observation space. Although from the point of view of the object coordinates, a certain movement is made in the world coordinate system, this movement does not change the relative position of the object and the camera, and also successfully moves the camera to the origin of the world coordinates, so the result is equal to moving the object to the observation space.</p><p>So how do you get this view matrix?</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680244406/origin-of-ray/WX20230331-143313_2x_om55nf.png" alt="" /></p><p>This method is more complicated</p><p>We can use a better property here, that is, the rotation matrix is actually an orthogonal matrix, the Inverse Matrix and the transpose matrix of the orthogonal matrix are the same, that is, we can find the matrix of the world coordinate axis transformed into the camera coordinate axis, and then find his transpose matrix, that is, the Inverse Matrix, which is the matrix of the camera coordinate axis transformed into the world coordinate axis</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680244572/origin-of-ray/WX20230331-143602_2x_cpsn3o.png" alt="" /></p><h2 id="projection-matrix"><a class="markdownIt-Anchor" href="#projection-matrix"></a> Projection matrix</h2><p>Just through the View matrix, the relative position of our camera and the object as a whole remains unchanged and moves to the position of the camera at the origin of the world coordinate system.</p><p>What is the purpose of this? Of course, there is an advantage that it is easy to understand, but in fact, it does not make sense for a calculator, because it is all multiplied by a matrix, and the amount of calculation will not make a difference.</p><p>Another advantage of this is to reduce the calculation of the projection matrix.</p><p>Our projection matrix is divided into two types, one is parallel projection and the other is orthogonal projection:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680244940/origin-of-ray/WX20230331-144201_2x_are3h7.png" alt="" /></p><h3 id="parallel-projection"><a class="markdownIt-Anchor" href="#parallel-projection"></a> Parallel projection</h3><p>Let’s first look at the relatively simple parallel projection</p><p>A relatively simple way to understand this projection is to just throw away the z-axis, which is the coordinate of the final point on the screen, and then both the x and y directions are translated and scaled between [-1, 1]. The reason why we can just throw away z here is that our camera is moved to the origin and in the negative direction of the z-axis.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680245161/origin-of-ray/WX20230331-144545_2x_f4qhis.png" alt="" /></p><p>However, dropping the z-axis cannot be done yet. We still need the information of z to do in-depth tests later. What we need to do now is to normalize x, y, z to the cube of $[-1,1] ^ 3 $</p><p>As shown in the figure below, in the parallel projection, we start with a cube in the observation space. We need to move the center of this cube to the origin and scale it to a cube with side length 1</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680245344/origin-of-ray/WX20230331-144846_2x_jxcjxv.png" alt="" /></p><h3 id="orthogonal-projection"><a class="markdownIt-Anchor" href="#orthogonal-projection"></a> Orthogonal projection</h3><p>The difference between orthogonal projection and parallel projection is that there is a near-large and far-small effect, and its initial observation space is not a cube, but a ladder</p><p>We are looking for this ladder normalization matrix to be divided into two steps:</p><ol><li>Scale the ladder to a cube, and the observation space at this time is equivalent to a parallel projection</li><li>Reuse normalized matrices with parallel projections</li></ol><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680245630/origin-of-ray/WX20230331-145336_2x_iwwpge.png" alt="" /></p><p>So we’re focusing on the first step right now</p><p>And because our current camera is facing the negative direction of z, so the zoom bottom will not affect the z coordinate, we only need to focus on x and y, we take the y coordinate for example:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1680245798/origin-of-ray/WX20230331-145627_2x_bdvmtg.png" alt="" /></p><p>Similarly, the left side of x becomes $x '=\ frac {n} {z} x $</p><p>Then at this time, our transformation matrix can be written. First, the transformation of the orthogonal projection space into the parallel projection space</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>M</mi><mrow><mi>p</mi><mi>r</mi><mi>e</mi><mi>s</mi><mi>p</mi><mo>−</mo><mi>o</mi><mi>r</mi><mi>t</mi><mi>h</mi><mi>o</mi></mrow></msub><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>x</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>y</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>z</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mtext> </mtext><mi>f</mi><mi>r</mi><mi>a</mi><mi>c</mi><mi>n</mi><mi>z</mi><mi>x</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>f</mi><mi>r</mi><mi>a</mi><mi>c</mi><mi>n</mi><mi>z</mi><mi>y</mi><mtext> </mtext><mi>z</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>n</mi><mi>x</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mrow><mi>n</mi><mi>y</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><msup><mi>z</mi><mn>2</mn></msup></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>z</mi></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow><mspace linebreak="newline"></mspace><mi>T</mi><mi>h</mi><mi>a</mi><mi>t</mi><mi>i</mi><mi>s</mi><mspace linebreak="newline"></mspace><msub><mi>M</mi><mrow><mi>p</mi><mi>r</mi><mi>e</mi><mi>s</mi><mi>p</mi><mo>−</mo><mi>o</mi><mi>r</mi><mi>t</mi><mi>h</mi><mi>o</mi></mrow></msub><mo>=</mo><mrow><mo fence="true">[</mo><mtable rowspacing="0.15999999999999992em" columnspacing="1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>n</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>n</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mi>z</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>1</mn></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="false"><mn>0</mn></mstyle></mtd></mtr></mtable><mo fence="true">]</mo></mrow></mrow><annotation encoding="application/x-tex">M_{presp-ortho}\begin{bmatrix}x \\ y \\ z \\ 1\end{bmatrix} = \begin{bmatrix}\ frac {n} {z} x\\ frac {n} {z} y\ z\\ 1\end{bmatrix} = \begin{bmatrix}nx \\ ny \\ z^2 \\ z\end{bmatrix}\\That is\\M_{presp-ortho} = \begin{bmatrix}n &amp; 0 &amp; 0 &amp; 0 \\0 &amp; n &amp; 0 &amp; 0 \\0 &amp; 0 &amp; z &amp; 0 \\0 &amp; 0 &amp; 1 &amp; 0 \\\end{bmatrix}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.80303em;vertical-align:-2.15003em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361079999999999em;"><span style="top:-2.5500000000000003em;margin-left:-0.10903em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">p</span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">x</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:3.6010299999999997em;vertical-align:-1.55002em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.05em;"><span style="top:-4.21em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mspace"> </span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">a</span><span class="mord mathnormal">c</span><span class="mord"><span class="mord mathnormal">n</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span><span class="mord mathnormal">x</span></span></span><span style="top:-3.0099999999999993em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="mord mathnormal">a</span><span class="mord mathnormal">c</span><span class="mord"><span class="mord mathnormal">n</span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span><span class="mspace"> </span><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span><span style="top:-1.8099999999999994em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.5500000000000007em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.0510099999999998em;"><span style="top:-2.2500000000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.8099900000000004em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.05101em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.55002em;"><span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:4.80303em;vertical-align:-2.15003em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mord mathnormal">x</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.03588em;">y</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141079999999999em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.69444em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mord mathnormal">h</span><span class="mord mathnormal">a</span><span class="mord mathnormal">t</span><span class="mord mathnormal">i</span><span class="mord mathnormal">s</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.969438em;vertical-align:-0.286108em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361079999999999em;"><span style="top:-2.5500000000000003em;margin-left:-0.10903em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">e</span><span class="mord mathnormal mtight">s</span><span class="mord mathnormal mtight">p</span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">o</span><span class="mord mathnormal mtight" style="margin-right:0.02778em;">r</span><span class="mord mathnormal mtight">t</span><span class="mord mathnormal mtight">h</span><span class="mord mathnormal mtight">o</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286108em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:4.80303em;vertical-align:-2.15003em;"></span><span class="minner"><span class="mopen"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎣</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎢</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎡</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span><span class="mord"><span class="mtable"><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">n</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.04398em;">z</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:0.5em;"></span><span class="arraycolsep" style="width:0.5em;"></span><span class="col-align-c"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6500000000000004em;"><span style="top:-4.8100000000000005em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-3.61em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-2.4099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span><span style="top:-1.2099999999999997em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.1500000000000004em;"><span></span></span></span></span></span></span></span><span class="mclose"><span class="delimsizing mult"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.6529999999999996em;"><span style="top:-1.6499900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎦</span></span></span><span style="top:-2.79999em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.3959900000000003em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-3.4119800000000002em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎥</span></span></span><span style="top:-4.653em;"><span class="pstrut" style="height:3.1550000000000002em;"></span><span class="delimsizinginner delim-size4"><span>⎤</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.15003em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>Then the formal orthogonal projection View matrix is $M_ {press-ortho} $multiplied by the parallel projection View matrix</p><p>At this point, we have completed the transformation of a point from model space to normalized space in the world coordinate system</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;Recently, I began to re-learn the knowledge of Computer Graphics, so I set my eyes on GAMES101. While watching, I did it and summarized it. This time I summarize the basic knowledge of linear algebra and how to do model transformation in the game. Finally, finish homework 1.&lt;/p&gt;</summary>
    
    
    
    <category term="Unity" scheme="https://sunra.top/en/categories/Unity/"/>
    
    
  </entry>
  
  <entry>
    <title>How to Convert Canvas to SVG</title>
    <link href="https://sunra.top/en/posts/4708/"/>
    <id>https://sunra.top/en/posts/4708/</id>
    <published>2023-03-30T04:27:55.000Z</published>
    <updated>2026-06-13T06:03:37.117Z</updated>
    
    <content type="html"><![CDATA[<p>Before, I made a request for a relational graph. Because exporting png and other images will be distorted when enlarged, I hope to export them as vector graphs. However, the export graph function that comes with G6 cannot be exported as SVG in Canvas mode, and SVG mode has many features that are not supported, so I tried to find a way to export Canvas as SVG.</p><span id="more"></span><p>This code uses an old library called canvas-to-svg</p><p>This library simulates canvas and exposes some canvas apis, which can finally be exported as svg</p><p>It should be noted that some canvas APIs do not support, such as setTransform, resetTransform, etc. If you need to use these two APIs, you can split them into translate and rotate, etc</p><p>Directly upload the code:</p><figure class="highlight ts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">CanvasToSVG</span> <span class="keyword">from</span> <span class="string">&#x27;canvas-to-svg&#x27;</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">addTextWaterMaskToCanvas</span>(<span class="params"></span></span><br><span class="line"><span class="params">  <span class="attr">context</span>: <span class="title class_">CanvasRenderingContext2D</span>,</span></span><br><span class="line"><span class="params">  <span class="attr">textWaterMask</span>: <span class="built_in">string</span>,</span></span><br><span class="line"><span class="params"></span>) &#123;</span><br><span class="line">  context.<span class="property">font</span> = <span class="string">&#x27;16px Microsoft YaHei&#x27;</span>;</span><br><span class="line">  context.<span class="property">fillStyle</span> = <span class="string">&#x27;#F2F3F5&#x27;</span>;</span><br><span class="line">  <span class="keyword">const</span> &#123; width, height &#125; = context.<span class="property">canvas</span>;</span><br><span class="line">  <span class="keyword">const</span> textMaskCountHorizontal = <span class="title class_">Math</span>.<span class="title function_">max</span>(<span class="number">1</span>, width / <span class="number">150</span>);</span><br><span class="line">  <span class="keyword">const</span> textMaskCountVertical = <span class="title class_">Math</span>.<span class="title function_">max</span>(<span class="number">1</span>, height / <span class="number">150</span>);</span><br><span class="line">  <span class="keyword">const</span> fwidth = width / textMaskCountHorizontal;</span><br><span class="line">  <span class="keyword">const</span> fheight = height / textMaskCountVertical;</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">let</span> hh = <span class="number">0</span>; hh &lt; height; hh += fheight) &#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> ww = <span class="number">0</span>; ww &lt; width; ww += fwidth) &#123;</span><br><span class="line">      context.<span class="title function_">translate</span>(ww, hh);</span><br><span class="line">      context.<span class="title function_">rotate</span>(-<span class="title class_">Math</span>.<span class="title function_">atan</span>(height / width));</span><br><span class="line">      context.<span class="title function_">fillText</span>(textWaterMask, -fwidth / <span class="number">2</span>, fheight / <span class="number">2</span>);</span><br><span class="line">      context.<span class="title function_">rotate</span>(<span class="title class_">Math</span>.<span class="title function_">atan</span>(height / width));</span><br><span class="line">      context.<span class="title function_">translate</span>(-ww, -hh);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">downloadFullImageWithWaterMaskCreator</span>(<span class="params"></span></span><br><span class="line"><span class="params">  <span class="attr">graphInstance</span>: <span class="title class_">IGraph</span> | <span class="literal">null</span>,</span></span><br><span class="line"><span class="params">  <span class="attr">textWaterMask</span>: <span class="built_in">string</span>,</span></span><br><span class="line"><span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">function</span> (<span class="params"></span></span><br><span class="line"><span class="params">    <span class="attr">name</span>?: <span class="built_in">string</span>,</span></span><br><span class="line"><span class="params">    <span class="attr">type</span>?: <span class="title class_">DataUrlType</span>,</span></span><br><span class="line"><span class="params">    <span class="attr">imageConfig</span>?: &#123;</span></span><br><span class="line"><span class="params">      backgroundColor?: <span class="built_in">string</span>;</span></span><br><span class="line"><span class="params">      padding?: <span class="built_in">number</span> | <span class="built_in">number</span>[];</span></span><br><span class="line"><span class="params">    &#125;,</span></span><br><span class="line"><span class="params">    <span class="attr">callback</span>?: (success: <span class="built_in">boolean</span>) =&gt; <span class="built_in">void</span>,</span></span><br><span class="line"><span class="params">  </span>) &#123;</span><br><span class="line">    graphInstance?.<span class="title function_">toFullDataURL</span>(</span><br><span class="line">      <span class="function"><span class="params">res</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> image = <span class="keyword">new</span> <span class="title class_">Image</span>();</span><br><span class="line">        image.<span class="property">src</span> = res;</span><br><span class="line">        image.<span class="property">onload</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">          <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// const canvas = document.createElement(&#x27;canvas&#x27;);</span></span><br><span class="line">            <span class="comment">// canvas.width = image.width;</span></span><br><span class="line">            <span class="comment">// canvas.height = image.height;</span></span><br><span class="line">            <span class="comment">// const context = canvas.getContext(&#x27;2d&#x27;);</span></span><br><span class="line">            <span class="keyword">const</span> context = <span class="keyword">new</span> <span class="title class_">CanvasToSVG</span>(image.<span class="property">width</span>, image.<span class="property">height</span>);</span><br><span class="line">            <span class="keyword">if</span> (context &amp;&amp; name) &#123;</span><br><span class="line">              context.<span class="title function_">rect</span>(<span class="number">0</span>, <span class="number">0</span>, image.<span class="property">width</span>, image.<span class="property">height</span>);</span><br><span class="line">              context.<span class="title function_">drawImage</span>(image, <span class="number">0</span>, <span class="number">0</span>, image.<span class="property">width</span>, image.<span class="property">height</span>);</span><br><span class="line"></span><br><span class="line">              <span class="title function_">addTextWaterMaskToCanvas</span>(context, textWaterMask);</span><br><span class="line"></span><br><span class="line">              <span class="comment">// downloadCanvasImage(canvas, name, type);</span></span><br><span class="line"></span><br><span class="line">              <span class="keyword">const</span> svg = context.<span class="title function_">getSerializedSvg</span>(<span class="literal">true</span>);</span><br><span class="line">              <span class="keyword">const</span> svgData = <span class="variable constant_">URL</span>.<span class="title function_">createObjectURL</span>(</span><br><span class="line">                <span class="keyword">new</span> <span class="title class_">Blob</span>([svg], &#123; <span class="attr">type</span>: <span class="string">&#x27;image/svg&#x27;</span> &#125;),</span><br><span class="line">              );</span><br><span class="line">              <span class="keyword">const</span> downloadLink = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;a&#x27;</span>);</span><br><span class="line">              downloadLink.<span class="property">download</span> = <span class="string">`<span class="subst">$&#123;name&#125;</span>.svg`</span>;</span><br><span class="line">              downloadLink.<span class="property">href</span> = svgData;</span><br><span class="line">              downloadLink.<span class="title function_">click</span>();</span><br><span class="line"></span><br><span class="line">              callback?.(<span class="literal">true</span>);</span><br><span class="line">            &#125;</span><br><span class="line">          &#125; <span class="keyword">catch</span> &#123;</span><br><span class="line">            callback?.(<span class="literal">false</span>);</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;;</span><br><span class="line"></span><br><span class="line">        image.<span class="property">onerror</span> = <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">          callback?.(<span class="literal">false</span>);</span><br><span class="line">        &#125;;</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="keyword">type</span>,</span><br><span class="line">      imageConfig,</span><br><span class="line">    );</span><br><span class="line">  &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;Before, I made a request for a relational graph. Because exporting png and other images will be distorted when enlarged, I hope to export them as vector graphs. However, the export graph function that comes with G6 cannot be exported as SVG in Canvas mode, and SVG mode has many features that are not supported, so I tried to find a way to export Canvas as SVG.&lt;/p&gt;</summary>
    
    
    
    <category term="Sundry" scheme="https://sunra.top/en/categories/Sundry/"/>
    
    
  </entry>
  
  <entry>
    <title>Greedy algorithm and simulated annealing algorithm</title>
    <link href="https://sunra.top/en/posts/63479/"/>
    <id>https://sunra.top/en/posts/63479/</id>
    <published>2023-03-24T06:15:46.000Z</published>
    <updated>2026-06-13T06:03:37.124Z</updated>
    
    <content type="html"><![CDATA[<p>Greedy algorithm is a relatively common algorithm. The essence of greed is to choose the local optimal of each stage to achieve the global optimal. Simulated annealing algorithms are more common in artificial intelligence.</p><p>The reason why these two algorithms are considered together is that the simulated annealing algorithm is like an enhanced version of the greedy algorithm.</p><p>If the local optimal solution of each step of a problem cannot obtain the global optimal solution, the algorithm thinking of our conventional front-end and back-end programmers is Dynamic Programming.</p><p>But for AI development, the parameters may be hundreds of millions of levels, there is no way Dynamic Programming, this time you can try to use simulated annealing algorithm to jump out of this part with a certain probability, to find a better answer in the whole, but in fact This algorithm is not like a conventional algorithm, and will get an inevitable result.</p><p>This article summarizes and compares the two algorithms together to see where they are applicable and how to use them.</p><span id="more"></span><h1 id="greedy-algorithm"><a class="markdownIt-Anchor" href="#greedy-algorithm"></a> Greedy algorithm</h1><h2 id="what-is-a-greedy-algorithm"><a class="markdownIt-Anchor" href="#what-is-a-greedy-algorithm"></a> What is a greedy algorithm</h2><p>The essence of greed is to choose the local optimum of each stage, so as to achieve the global optimum.</p><p>This is a bit abstract, let’s take an example:</p><p>For example, if you have a pile of banknotes, you can take ten of them. If you want to reach the maximum amount, how do you take them?</p><p>Specify that you take the largest amount each time, and the end result is to take the largest amount of money.</p><p>Each time you take the largest is the local optimal, and finally take the largest amount of money is to launch the global optimal.</p><p>As another example, if there are a bunch of boxes, and you have a backpack with a volume of n, how to fill the backpack as much as possible, if you still choose the largest box every time, it will not work. At this time, Dynamic Programming is needed.</p><h2 id="when-to-use-a-greedy-algorithm"><a class="markdownIt-Anchor" href="#when-to-use-a-greedy-algorithm"></a> When to use a greedy algorithm</h2><p>To be honest, there is no fixed routine for greedy algorithms.</p><p>So the only difficulty is how to use the local optimum to derive the overall optimum.</p><p>So how can we see if the local optimum can lead to the overall optimum? Are there any fixed strategies or routines?</p><p>Sorry, no! Manually simulate by yourself. If the simulation is feasible, you can try the greedy strategy. If it is not feasible, Dynamic Programming may be required.</p><p>A colleague asked how to verify whether a greedy algorithm can be used?</p><p>The best strategy is to give counterexamples. If you can’t think of counterexamples, try greed.</p><h2 id="greedy-algorithm-general-steps"><a class="markdownIt-Anchor" href="#greedy-algorithm-general-steps"></a> Greedy algorithm general steps:</h2><ul><li>Break down the problem into several sub-problems</li><li>Find the right greedy strategy</li><li>Solve the optimal solution for each sub-problem</li><li>Stack locally optimal solutions into globally optimal solutions</li></ul><p>These four steps are actually too theoretical. We usually do greedy topics, and it is difficult to think according to these four steps. It is really a bit “chicken ribs”.</p><p>When doing the question, as long as you think clearly, what is the local optimal, if you deduce the global optimal, it is actually enough.</p><h1 id="simulated-annealing-algorithm"><a class="markdownIt-Anchor" href="#simulated-annealing-algorithm"></a> Simulated annealing algorithm</h1><h2 id="metal-annealing-principle"><a class="markdownIt-Anchor" href="#metal-annealing-principle"></a> Metal annealing principle</h2><p>Metal annealing is a metal heat treatment process in which the metal is heated to a certain temperature, kept for a sufficient time, and then cooled at a suitable speed (usually slow cooling, sometimes controlled cooling). The simulated annealing algorithm is derived from the principle of solid annealing, which heats the solid to a sufficiently high temperature, and then allows it to cool slowly. When heated, the internal particles of the solid become disordered with the temperature rise, and the internal energy increases, while when slowly cooled, the particles gradually become Orderly, reaching an equilibrium state at each temperature, and finally reaching the ground state at room temperature, the internal energy is minimized.</p><p>When in a low temperature state, the molecules in the solid have very low internal energy and vibrate in a small range in their original position. If the solid is heated to a certain temperature, the internal energy of the molecules will increase, the thermal movement will intensify, and the disorder of the molecular arrangement will increase. At this time, the temperature is slowly lowered, and at each temperature an equilibrium state (that is, a quasi-static process) is reached, the energy of the molecules gradually decreases, and eventually returns to the state of orderly arrangement, and the internal energy of the molecules also drops to a minimum.</p><h2 id="simulated-annealing-algorithm-2"><a class="markdownIt-Anchor" href="#simulated-annealing-algorithm-2"></a> Simulated annealing algorithm</h2><p>The earliest idea of simulated annealing algorithm (Simulated Annealing, SA) was proposed by N. Metropolis et al in 1953. In 1983, S. Kirkpatrick et al successfully introduced the annealing idea into the field of combinatorial optimization. It is a stochastic optimization algorithm based on Monte-Carlo iterative solution strategy, and its starting point is based on the similarity between the annealing process of solid matter in physics and general combinatorial optimization problems.</p><p>Before introducing simulated annealing, it is necessary to introduce the mountain climbing algorithm.</p><h3 id="hill-climbing-algorithm"><a class="markdownIt-Anchor" href="#hill-climbing-algorithm"></a> Hill climbing algorithm</h3><p>The hill climbing algorithm is a simple greedy search algorithm, which selects an optimal solution from the adjacent solution space of the current solution as the current solution every time until a local optimal solution is reached.</p><p>The implementation of the hill-climbing algorithm is very simple, and its main disadvantage is that it will fall into the local optimal solution, and it may not be able to search for the global optimal solution. As shown in the figure above: Assuming that point C is the current solution, the hill-climbing algorithm will stop searching when it searches for the local optimal solution at point A, because no matter where point A moves in that direction, it cannot get a better solution.</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1679639508/origin-of-ray/2010122016525713_tp8p5t.png" alt="" /></p><h3 id="core-idea-of-simulated-annealing"><a class="markdownIt-Anchor" href="#core-idea-of-simulated-annealing"></a> Core idea of simulated annealing</h3><p>Simulated annealing is actually a greedy algorithm, but its search process introduces random factors. The simulated annealing algorithm accepts a solution that is worse than the current solution with a certain probability, so it is possible to jump out of this local optimal solution and achieve a global optimal solution.</p><p>The simulated annealing algorithm starts from a higher initial temperature, with the continuous decline of temperature parameters, combined with certain probability sudden jump characteristics, randomly finds the global optimal solution of the target function in the solution space, that is, the local optimal solution can probabilistically jump out and eventually tend to the global optimal.</p><p>The calculation of “certain probability” here refers to the annealing process of metal smelting, which is also the origin of the name of the simulated annealing algorithm. The temperature T is regarded as the control parameter, the target function value f is regarded as the internal energy E, and a state of a solid at a certain temperature T corresponds to a solution<br />Then the algorithm attempts to reduce the target function f (internal energy E) as the control parameter T decreases, until it tends to the global minimum (the lowest energy state at low temperature in annealing), just like the metal annealing process.</p><h3 id="mathematical-principles-of-simulated-annealing"><a class="markdownIt-Anchor" href="#mathematical-principles-of-simulated-annealing"></a> Mathematical principles of simulated annealing</h3><p>From the above, we know that the global optimal solution of the target function will be randomly found in the solution space in combination with the probability sudden jump characteristic. So what is the specific mechanism for updating the solution? If the new solution is better than the current solution, the new solution is accepted, otherwise it is judged whether to accept the new solution based on the Metropolis criterion. The acceptance probability is:</p><p class='katex-block katex-error' title='ParseError: KaTeX parse error: No such environment: equation at position 7: \begin{̲e̲q̲u̲a̲t̲i̲o̲n̲}̲P = \begin{cas…'>\begin{equation}P = \begin{cases}    1 &amp; E_{t + 1} &lt; E_t;\\    e^{-\frac{E_{t + 1} - E_t}{kT}} &amp; E_{t + 1} \geq E_t;\end{cases}\end{equation}</p><p>Assuming that the solution of the search at the current time is $x_t $, and the corresponding system energy (target function) is $E_t $, a random perturbation is applied to the search point to generate a new solution $x_ {t + 1} $, and accordingly, the system energy is $E_ {t + 1} $, then the acceptance probability of the system from the search point to the transition is the above formula.</p><p>That is, if the energy corresponding to the new solution is lower, then the probability of acceptance is 1, that is, it must be accepted. If the energy corresponding to the new solution is high, then accept the new solution with the probability of $e ^ {-\ frac {E_ {t + 1} - E_t} {kT}} $, that is, use this probability to jump out of this local optimal solution.</p><p>This process is to randomly select x, and then find a corresponding E lowest x out, where E is lower corresponding to our specific algorithm is closer to the goal we need</p><p>There is also a problem here, which is how to choose the size of each change in x when we randomly select x.</p><p>This problem is actually the origin of the word’annealing ', that is, the temperature will gradually decrease, and the magnitude of x change will become smaller and smaller.</p><h3 id="simulated-annealing-process"><a class="markdownIt-Anchor" href="#simulated-annealing-process"></a> Simulated annealing process</h3><p>The essence of the algorithm is divided into two layers of cycles. At any temperature level, random disturbances generate a new solution, and calculate the change of the target function value to decide whether to accept it. Since the initial temperature of the algorithm is relatively high, the new solution that increases E may also be accepted initially, so it can jump out of the local minimum, and then by slowly reducing the temperature, the algorithm may eventually converge to the global optimal solution. The specific process is:</p><ol><li>Let $T = T_0 $, representing the initial temperature at which the annealing starts, randomly generate an initial solution $x_0 $, and calculate the corresponding target function value $E_0 $;</li><li>Let $T = kT $, where k is between 0 and 1, which is the rate of temperature drop;</li><li>Apply random perturbation to the current solution $x_t $, generate a new solution $x_ {t + 1} $in its neighborhood, and calculate the corresponding target function value $E_ {t + 1} <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow></mrow><annotation encoding="application/x-tex"></annotation></semantics></math></span><span class="katex-html" aria-hidden="true"></span></span>\Delta E =E_{t+1} - E_t$</li><li>If $\ Delta E &lt; 0 $accepts the new solution as the current solution, otherwise it is judged whether to accept the new solution according to the probability $e ^ {-\ frac {\ Delta E} {kT}} $;</li><li>Repeat the disturbance and acceptance process L times at temperature T, i.e. perform steps 3 and 4;</li><li>Determine whether the temperature reaches the termination temperature level, if so, terminate the algorithm, otherwise return to step 2.</li></ol><p>There are a few points to note:</p><ul><li>The selection of the initial point has a certain impact on the results of the algorithm, it is best to run multiple times to make a comprehensive judgment on the results.</li><li>In the early stage of algorithm operation, the temperature drops quickly to avoid accepting too many poor results. As the running time increases, the temperature drop slows down to stabilize the results faster.</li><li>When the number of iterations increases to a certain number, the result may have reached stability, but there is still some time before the algorithm ends. Appropriate output conditions should be added when designing the program, and the program can be ended if the output conditions are met.</li></ul><h2 id="application-of-simulated-annealing"><a class="markdownIt-Anchor" href="#application-of-simulated-annealing"></a> Application of simulated annealing</h2><ul><li><p>The application of simulated annealing algorithm in VLSI design, using simulated annealing algorithm to optimize the design of VLSI (Very Large Scale Integration, Very Large Scale Integrated Circuit), is one of the most successful application examples of simulated annealing algorithm at present. The simulated annealing algorithm can almost complete all optimized VLSI design work well. Such as global wiring, board layout, layout and logic minimization, etc.</p></li><li><p>Simulated annealing algorithm can be used for image restoration and other work, that is, to restore a contaminated image into a clear original image and filter out the distorted part. Therefore, its application prospect in image processing is broad.</p></li><li><p>Application of simulated annealing algorithm in neural network computer. The simulated annealing algorithm has the ability to jump out of the trap of local optima. In the Boltzmann machine, even if the system falls into the trap of local optima, after a period of time, it can jump out again, and the system will eventually converge in the direction of the global optimal value.</p></li><li><p>In the force-oriented layout algorithm, the idea of simulated annealing is actually implicit. At the beginning, all nodes are randomly arranged, and then the position of the node changes due to the action of the force between the nodes. The position change is equivalent to the x change, and the changed position, if the resultant force received by the node decreases, which is equivalent to a decrease in energy E, we accept the new solution, and then as the resultant force decreases, it is actually equivalent to a decrease in T, so the impact on the position will become smaller, the full resultant force decreases below a certain threshold, and the position change is not large, and we think the algorithm converges to the result.</p></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;Greedy algorithm is a relatively common algorithm. The essence of greed is to choose the local optimal of each stage to achieve the global optimal. Simulated annealing algorithms are more common in artificial intelligence.&lt;/p&gt;
&lt;p&gt;The reason why these two algorithms are considered together is that the simulated annealing algorithm is like an enhanced version of the greedy algorithm.&lt;/p&gt;
&lt;p&gt;If the local optimal solution of each step of a problem cannot obtain the global optimal solution, the algorithm thinking of our conventional front-end and back-end programmers is Dynamic Programming.&lt;/p&gt;
&lt;p&gt;But for AI development, the parameters may be hundreds of millions of levels, there is no way Dynamic Programming, this time you can try to use simulated annealing algorithm to jump out of this part with a certain probability, to find a better answer in the whole, but in fact This algorithm is not like a conventional algorithm, and will get an inevitable result.&lt;/p&gt;
&lt;p&gt;This article summarizes and compares the two algorithms together to see where they are applicable and how to use them.&lt;/p&gt;</summary>
    
    
    
    <category term="Algorithm" scheme="https://sunra.top/en/categories/Algorithm/"/>
    
    
  </entry>
  
  <entry>
    <title>Tailwind CSS Introduction</title>
    <link href="https://sunra.top/en/posts/53142/"/>
    <id>https://sunra.top/en/posts/53142/</id>
    <published>2023-03-18T01:17:30.000Z</published>
    <updated>2026-06-13T06:03:37.140Z</updated>
    
    <content type="html"><![CDATA[<p>Tailwind this CSS framework is not something new, but has not been to study, recently there is a need to look at it, it looks relatively simple.</p><p>This thing looks like a new DSL or something, providing many commonly used and built-in CSS styles, encapsulating them into syntax, and then providing a PostCSS plugin to process the encapsulated syntax back into ordinary CSS.</p><p>All we need to do is install Tailwind’s PostCSS plugin and use his encapsulated DSL.</p><span id="more"></span><h1 id="what-is-postcss"><a class="markdownIt-Anchor" href="#what-is-postcss"></a> What is PostCSS?</h1><p>In web application development, the writing of CSS code is an important part. From the original CSS1 to the current CSS3, and then to the next version of the CSS specification, the specification itself has been constantly evolving. This has brought efficiency improvements to developers. However, similar to the situation of specifications in other web fields, CSS specifications have always had various problems in terms of browser compatibility. The progress of implementing CSS specifications in different browsers also varies greatly. In addition, there is still a certain gap between the development speed of the CSS specification itself and the expectations of the community. This is also an important reason why CSS preprocessing languages such as SASS and LESS can become popular. SASS and LESS provide many more practical features and also reflect the needs of developers for CSS languages. PostCSS, which is introduced in this article, is a popular tool for processing CSS. PostCSS adds endless possibilities to CSS processing with its powerful plugin system.</p><p>PostCSS itself is a relatively single-function tool. It provides a way to handle CSS with JavaScript code. It is responsible for parsing CSS code into an Abstract Syntax Tree (AST) structure, which is then handled by plugins. Plugins can perform various operations based on the AST of CSS code, such as supporting variables and mixins, increasing browser-related declaration prefixes, or transpiling style rules using future CSS specifications into formats supported by current CSS specifications. From this perspective, the strength of PostCSS lies in its constantly evolving plugin system. Currently, PostCSS has more than 200 plugins with different functions. Developers can also develop their own PostCSS plugins according to the needs of the project.</p><p>** PostCSS has brought controversy over its classification in the community since its birth. This is mainly due to the post in its name, which is easily reminiscent of PostCSS being used as a post-processor for CSS, thus being compared to existing CSS pre-processor languages such as SASS and LESS. Analogy **.</p><p>In fact, there are only two main functions of PostCSS: the first is to parse CSS into an AST that JavaScript can manipulate, and the second is to call a plugin to process the AST and get the result. Therefore, PostCSS cannot simply be classified as a CSS preprocessing or post-processing tool. PostCSS can perform many tasks, covering both preprocessing and post-processing in the traditional sense. PostCSS is a brand new tool that brings front-end developers a different way of handling CSS.</p><h1 id="how-to-use-postcss"><a class="markdownIt-Anchor" href="#how-to-use-postcss"></a> How to use PostCSS</h1><p>PostCSS is generally not used alone, but integrated with existing build tools. PostCSS can be integrated with mainstream build tools such as Webpack, Grunt, and Gulp. After completing the integration, select the PostCSS plugin that meets the functional requirements and configure it.</p><p>Postcss-loader is used in Webpack to perform plug-in processing. In Listing 1, postcss-loader is used to process .css files, added after style-loader and css-loader. An additional postcss method returns the required PostCSS plug-in. The role of require (‘autoprefixer’) is to load the Autoprefixer plug-in.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> path = <span class="built_in">require</span>(<span class="string">&#x27;path&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line"><span class="attr">context</span>: path.<span class="title function_">join</span>(__dirname, <span class="string">&#x27;app&#x27;</span>),</span><br><span class="line"><span class="attr">entry</span>: <span class="string">&#x27;./app&#x27;</span>,</span><br><span class="line"><span class="attr">output</span>: &#123;</span><br><span class="line"><span class="attr">path</span>: path.<span class="title function_">join</span>(__dirname, <span class="string">&#x27;dist&#x27;</span>),</span><br><span class="line"><span class="attr">filename</span>: <span class="string">&#x27;bundle.js&#x27;</span></span><br><span class="line">&#125;,</span><br><span class="line"><span class="attr">module</span>: &#123;</span><br><span class="line"><span class="attr">loaders</span>: [</span><br><span class="line">&#123;</span><br><span class="line"><span class="attr">test</span>: <span class="regexp">/\.css$/</span>,</span><br><span class="line"><span class="attr">loader</span>: <span class="string">&quot;style-loader!css-loader!postcss-loader&quot;</span></span><br><span class="line">&#125;</span><br><span class="line">]</span><br><span class="line">&#125;,</span><br><span class="line"><span class="attr">postcss</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line"><span class="keyword">return</span> [<span class="built_in">require</span>(<span class="string">&#x27;autoprefixer&#x27;</span>)];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1 id="how-to-enable-and-set-up-tailwind"><a class="markdownIt-Anchor" href="#how-to-enable-and-set-up-tailwind"></a> How to enable and set up Tailwind</h1><h2 id="passed"><a class="markdownIt-Anchor" href="#passed"></a> passed</h2><p>For most projects (and to take advantage of Tailwind’s custom features), you will need to install Tailwind and its dependencies via npm.</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -D tailwindcss@latest postcss@latest autoprefixer@latest</span><br></pre></td></tr></table></figure><p>Since Tailwind does not automatically add browser engine prefixes to the generated CSS, we recommend installing autoprefixer to handle this issue, as shown in the code snippet above.</p><h2 id="as"><a class="markdownIt-Anchor" href="#as"></a> As</h2><p>Add tailwindcss and autoprefixer to your PostCSS configuration. In most cases, this is the postcss.config.js file in the root of the project, but it may also be the .postcssrc file or specified by the postcss key in the package.json file.</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// postcss.config.js</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">plugins</span>: &#123;</span><br><span class="line">    <span class="attr">tailwindcss</span>: &#123;&#125;,</span><br><span class="line">    <span class="attr">autoprefixer</span>: &#123;&#125;,</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="create-your-profile"><a class="markdownIt-Anchor" href="#create-your-profile"></a> Create your profile</h2><p>If you want to customize your Tailwind installation, you can generate a configuration file using the Tailwind CLI tool, which is included in the npm package tailwindcss.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx tailwindcss init</span><br></pre></td></tr></table></figure><p>This will create a minimal tailwind.config.js file in your project root directory.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// tailwind.config.js</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">purge</span>: [],</span><br><span class="line">  <span class="attr">darkMode</span>: <span class="literal">false</span>, <span class="comment">// or &#x27;media&#x27; or &#x27;class&#x27;</span></span><br><span class="line">  <span class="attr">theme</span>: &#123;</span><br><span class="line">    <span class="attr">extend</span>: &#123;&#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">variants</span>: &#123;&#125;,</span><br><span class="line">  <span class="attr">plugins</span>: [],</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="include"><a class="markdownIt-Anchor" href="#include"></a> Include</h2><p>If you have not yet created a CSS file, use the @tailwind directive to inject Tailwind’s base, components, and utilities styles:</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* ./your-css-folder/styles.css */</span></span><br><span class="line"><span class="keyword">@tailwind</span> base;</span><br><span class="line"><span class="keyword">@tailwind</span> components;</span><br><span class="line"><span class="keyword">@tailwind</span> utilities;</span><br></pre></td></tr></table></figure><p>Tailwind will replace these instructions at build time with all styles generated based on your configured design system.</p><p>If you are using postcss-import (or the tool behind it, such as Webpacker for Rails), please use our import instead of the @tailwind directive to avoid problems when importing any other files.</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">@import</span> <span class="string">&quot;tailwindcss/base&quot;</span>;</span><br><span class="line"><span class="keyword">@import</span> <span class="string">&quot;tailwindcss/components&quot;</span>;</span><br><span class="line"><span class="keyword">@import</span> <span class="string">&quot;tailwindcss/utilities&quot;</span>;</span><br></pre></td></tr></table></figure><p>If you are using a JavaScript framework like React or Vue that supports importing CSS files directly into JS, you can also skip creating CSS files entirely and directly import tailwindcss/tailwind.css, which already has all these instructions installed.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// app.js</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">&quot;tailwindcss/tailwind.css&quot;</span></span><br></pre></td></tr></table></figure><h2 id="generate-your"><a class="markdownIt-Anchor" href="#generate-your"></a> Generate your</h2><p>The way you actually build your project will depend on the tools you use. Your framework may include commands like npm run dev to start a development server that compiles CSS in the background, you may be running webpack yourself, or you may be using postcss-cli and running commands like postcss styles.css -o compiled.css.</p><h2 id="optimize-with-other-preprocessors"><a class="markdownIt-Anchor" href="#optimize-with-other-preprocessors"></a> Optimize with other preprocessors</h2><p>Since Tailwind is a PostCSS plugin, nothing prevents you from using Sass, Less, Stylus, or other preprocessors, just like you can use other PostCSS plugins such as Autoprefixer.</p><p>It is important to note that you do not need to use preprocessors in Tailwind - you usually write very little CSS in Tailwind projects, so using preprocessors is not as beneficial as in a project where you write a lot of custom CSS.</p><h3 id="build-time-import"><a class="markdownIt-Anchor" href="#build-time-import"></a> Build-time import</h3><p>One of the most useful features provided by the preprocessor is the ability to organize your CSS into multiple files and combine them at build time by processing @import statements in advance instead of in the browser.</p><p>The canonical plugin for handling PostCSS is postcss-import.</p><p>To use it, please install the plugin through npm.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install postcss-import</span><br></pre></td></tr></table></figure><p>Then make it the first plugin in the PostCS configuration.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// postcss.config.js</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">plugins</span>: [</span><br><span class="line">    <span class="built_in">require</span>(<span class="string">&#x27;postcss-import&#x27;</span>),</span><br><span class="line">    <span class="built_in">require</span>(<span class="string">&#x27;tailwindcss&#x27;</span>),</span><br><span class="line">    <span class="built_in">require</span>(<span class="string">&#x27;autoprefixer&#x27;</span>),</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>One important thing to note about postcss-import is that it strictly adheres to the CSS specification and does not allow the use of @import statements anywhere except at the top of the file.</p><h3 id="built-in-nesting-plugin-to-support-syntax-such-as-apply"><a class="markdownIt-Anchor" href="#built-in-nesting-plugin-to-support-syntax-such-as-apply"></a> Built-in Nesting plugin to support syntax such as’ @apply ’</h3><p>To add support for nested declarations, we recommend our bundled tailwindcss/nesting plugin, which is a PostCSS plugin that can wrap PostCSS nesting or PostCSS nesting, and serves as a compatibility layer to ensure that the nested plugin you choose correctly understands Tailwind’s custom syntax, such as @application and @screen.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// postcss.config.js</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">plugins</span>: [</span><br><span class="line">    <span class="built_in">require</span>(<span class="string">&#x27;postcss-import&#x27;</span>),</span><br><span class="line">    <span class="built_in">require</span>(<span class="string">&#x27;tailwindcss/nesting&#x27;</span>),</span><br><span class="line">    <span class="built_in">require</span>(<span class="string">&#x27;tailwindcss&#x27;</span>),</span><br><span class="line">    <span class="built_in">require</span>(<span class="string">&#x27;autoprefixer&#x27;</span>),</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="variables"><a class="markdownIt-Anchor" href="#variables"></a> Variables</h3><p>These days CSS variables (officially known as custom properties) have really good browser support, so you don’t need a preprocessor to use variables at all.</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-pseudo">:root</span> &#123;</span><br><span class="line">  <span class="attr">--theme-color</span>: <span class="number">#52b3d0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* ... */</span></span><br><span class="line"></span><br><span class="line"><span class="selector-class">.btn</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="built_in">var</span>(--theme-color);</span><br><span class="line">  <span class="comment">/* ... */</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>We use CSS variables extensively within Tailwind itself, so if you can use Tailwind, you can use native CSS variables.</p><p>You may also find that most of the things you’ve used variables for in the past can be replaced with Tailwind’s theme() function, which gives you access to all of your design tokens from your tailwind.config.js file directly in your CSS:</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.btn</span> &#123;</span><br><span class="line">  <span class="attribute">background-color</span>: <span class="built_in">theme</span>(<span class="string">&#x27;colors.blue.500&#x27;</span>);</span><br><span class="line">  <span class="attribute">padding</span>: <span class="built_in">theme</span>(<span class="string">&#x27;spacing.2&#x27;</span>) <span class="built_in">theme</span>(<span class="string">&#x27;spacing.4&#x27;</span>);</span><br><span class="line">  <span class="comment">/* ... */</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="vendor"><a class="markdownIt-Anchor" href="#vendor"></a> Vendor</h3><p>For automatically managing vendor prefixes in your CSS, you should use Autoprefixer.</p><p>To use it, install it via npm: - &gt; You can use the postcss-press-env plugin to add support for upcoming CSS features to your project.</p><p>To use it, please install it via npm.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install autoprefixer</span><br></pre></td></tr></table></figure><p>Then add it to the very end of your plugin list in your PostCSS configuration:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">plugins</span>: [</span><br><span class="line">    <span class="built_in">require</span>(<span class="string">&#x27;tailwindcss&#x27;</span>),</span><br><span class="line">    <span class="built_in">require</span>(<span class="string">&#x27;autoprefixer&#x27;</span>),</span><br><span class="line">  ]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="production-optimization"><a class="markdownIt-Anchor" href="#production-optimization"></a> Production optimization</h2><p>Using the default configuration, the development version of TailwindCSS is 3645.2kB uncompressed, 294.2kB compressed with Gzip, and 72.8kB compressed with Brotli.</p><p>This may sound huge, and that’s because design is huge.</p><p>In order to make the development experience as productive as possible, Tailwind generates thousands of functional classes for you, most of which you may not actually use.</p><p>Think of Tailwind as a giant Lego box - you dump it on the floor, build what you want to build, and then when you’re done, you put all the pieces you don’t need back into the box.</p><p>For example, Tailwind generates a margin utility for every dimension in your spacing scale, for every side of an element you might want to apply a margin to, and for every breakpoint used in your project. This results in hundreds of different combinations, all of which are important but not all of which are needed.</p><p>When building production, you should always use Tailwind’s purge option to tree-shake to optimize unused styles and optimize your final build size. When using Tailwind to remove unused styles, it’s hard to end up with more than 10kb of compressed CSS.</p><h3 id="write-cleanable"><a class="markdownIt-Anchor" href="#write-cleanable"></a> Write cleanable</h3><p>Before you start using the Purge feature, it’s important to understand how it works and build the right mental model to ensure you never accidentally remove important styles when building for production.</p><p>PurgeCSS (the library we use under the engine) is intentionally very naive in the way it looks for classes in HTML. It doesn’t try to parse your HTML and look for class attributes, nor does it dynamically execute your JavaScript - it just looks for any string that matches this Regular Expression throughout the file.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/[^<span class="language-xml"><span class="tag">&lt;&gt;</span>&quot;&#x27;`\s]*[^<span class="tag">&lt;&gt;</span>&quot;&#x27;`\s:]/g</span></span><br></pre></td></tr></table></figure><p>This can basically match any string separated by spaces, quotes, or angle brackets, including HTML tags, attributes, classes, and even the actual written content in your markup.</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;md:flex&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;md:flex-shrink-0&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">class</span>=<span class="string">&quot;rounded-lg md:w-56&quot;</span> <span class="attr">src</span>=<span class="string">&quot;/img/shopping.jpg&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;Woman paying for a purchase&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;mt-4 md:mt-0 md:ml-6&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;uppercase tracking-wide text-sm text-indigo-600 font-bold&quot;</span>&gt;</span></span><br><span class="line">      Marketing</span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;/get-started&quot;</span> <span class="attr">class</span>=<span class="string">&quot;block mt-1 text-lg leading-tight font-semibold text-gray-900 hover:underline&quot;</span>&gt;</span></span><br><span class="line">      Finding customers for your new business</span><br><span class="line">    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;mt-2 text-gray-600&quot;</span>&gt;</span></span><br><span class="line">      Getting a new business off the ground is a lot of hard work.</span><br><span class="line">      Here are five ideas you can use to find your first customers.</span><br><span class="line">    <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><p>This means that it is important to avoid dynamically creating classes with string concatenation in your template, otherwise PurgeCSS will not know to save these classes.</p><p>For example, do not use string connection.</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;text-&#123;&#123;  error  ?  &#x27;red&#x27;  :  &#x27;green&#x27;  &#125;&#125;-600&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><p>Instead, dynamically select a complete class name</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;&#123;&#123;  error  ?  &#x27;text-red-600&#x27;  :  &#x27;text-green-600&#x27;  &#125;&#125;&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><p>As long as a class name appears in your template, PurgeCSS will not delete it.</p><h3 id="remove-unused-css"><a class="markdownIt-Anchor" href="#remove-unused-css"></a> Remove unused CSS</h3><p>Basic purposes<br />To get started, use the purge option to provide a path array for all your template files.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// tailwind.config.js</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">purge</span>: [</span><br><span class="line">    <span class="string">&#x27;./src/**/*.html&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;./src/**/*.vue&#x27;</span>,</span><br><span class="line">    <span class="string">&#x27;./src/**/*.jsx&#x27;</span>,</span><br><span class="line">  ],</span><br><span class="line">  <span class="attr">theme</span>: &#123;&#125;,</span><br><span class="line">  <span class="attr">variants</span>: &#123;&#125;,</span><br><span class="line">  <span class="attr">plugins</span>: [],</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>For example, if you have a JS file in your project that dynamically switches some classes in your HTML, you should make sure to include the file in this list.</p><p>Now, whenever you set NODE_ENV to production when compiling CSS, Tailwind will automatically remove unused styles from your CSS.</p><h3 id="manually-enabled"><a class="markdownIt-Anchor" href="#manually-enabled"></a> Manually enabled</h3><p>If you want to manually control whether unused styles should be removed (rather than implicitly relying on environment variables), you can use an object syntax and provide the enabled option to specify your template using the content option.</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// tailwind.config.js</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">purge</span>: &#123;</span><br><span class="line">    <span class="attr">enabled</span>: <span class="literal">true</span>,</span><br><span class="line">    <span class="attr">content</span>: [<span class="string">&#x27;./src/**/*.html&#x27;</span>],</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// ...</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>** We recommend only removing unused styles in production, because removing them in development means that you need to re-compile your template at any time you change it, and compiling is much slower with PurgeCSS enabled. **</p><h1 id="how-to-use-tailwind"><a class="markdownIt-Anchor" href="#how-to-use-tailwind"></a> How to use Tailwind</h1><h2 id="functional-category-first"><a class="markdownIt-Anchor" href="#functional-category-first"></a> Functional category first</h2><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md flex items-center space-x-4&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;flex-shrink-0&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">img</span> <span class="attr">class</span>=<span class="string">&quot;h-12 w-12&quot;</span> <span class="attr">src</span>=<span class="string">&quot;/img/logo.svg&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;ChitChat Logo&quot;</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;text-xl font-medium text-black&quot;</span>&gt;</span>ChitChat<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;text-gray-500&quot;</span>&gt;</span>You have a new message!<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><p>In the above example, we used:</p><p>Use Tailwind’s flexbox and padding classes (flex, flex-shrink-0, and p-6) to control the overall card layout</p><ul><li><p>Use the max-width and margin function classes (max-w-sm and mx-auto) to set the card width and centered text</p></li><li><p>Use the’background color ‘,’ border radius’, and’box-shadow ‘function classes (’ bg-white ‘,’ rounded-xl ‘, and’shadow-md’) to set the appearance style of the card</p></li><li><p>Use the width and height function classes (w-12 and h-12) to set the size of the logo image</p></li></ul><p>Use the space-between function class (space-x-4) to handle spacing between logos and text</p><ul><li>Use font size, text color, and f ont-weight function classes (text-xl, t ext-black, font-medium, etc.) to style card text</li></ul><p>This method allows us to achieve a fully customized component design without writing a single line of custom CSS.</p><p>I know you’re thinking: “This is so tedious, what a mess!” You’re right, it’s kind of ugly. In fact, it’s almost impossible to think it’s a good idea when you first see it - you have to actually try it.</p><p>But once you actually build something this way, you’ll quickly notice some really important advantages:</p><ul><li><p>You didn’t waste your energy naming classes. No need to add some silly class names like’sidebar-inner-wrapper 'just to set some styles, no need to suffer from the perfect abstract naming of a flex container.</p></li><li><p>Your CSS stops growing. With traditional methods, the CSS file gets bigger every time a new feature is added. With function classes, everything is reusable, so you hardly need to write new CSS.</p></li><li><p>Changes will be safer. CSS is global, you never know what will break when you make changes. Classes in your HTML are local, so you can change them without worrying about other issues.</p></li></ul><p>When you realize how productive it is to use predefined functional classes in HTML, working any other way can feel like torture.</p><h2 id="responsive-design"><a class="markdownIt-Anchor" href="#responsive-design"></a> Responsive design</h2><p>Each function class in Tailwind can be conditionally applied to different breakpoints, which makes it easy for you to build complex responsive interfaces without leaving HTML.</p><ol><li>According to the commonly used device resolution scheme, there are 5 built-in breakpoints by default:</li></ol><table><thead><tr><th>Breakpoint Prefix</th><th>Minimum Width</th><th>CSS</th></tr></thead><tbody><tr><td>sm</td><td>640px</td><td>@media (min-width: 640px) { … }</td></tr><tr><td>md</td><td>768px</td><td>@media (min-width: 768px) { … }</td></tr><tr><td>lg</td><td>1024px</td><td>@media (min-width: 1024px) { … }</td></tr><tr><td>xl</td><td>1280px</td><td>@media (min-width: 1280px) { … }</td></tr><tr><td>2xl</td><td>1536px</td><td>@media (min-width: 1536px) { … }</td></tr><tr><td>To add a function class that only takes effect at a specific breakpoint, simply prefix the function class with the breakpoint name followed by the: character.</td><td></td><td></td></tr></tbody></table><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- Width of 16 by default, 32 on medium screens, and 48 on large screens --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">img</span> <span class="attr">class</span>=<span class="string">&quot;w-16 md:w-32 lg:w-48&quot;</span> <span class="attr">src</span>=<span class="string">&quot;...&quot;</span>&gt;</span></span><br></pre></td></tr></table></figure><p>This applies to every feature class in the framework, which means you can change anything at a given breakpoint, even things like character spacing and cursor style.</p><ol start="2"><li>Customize breakpoints</li></ol><p>You can fully customize your breakpoints in the tailwind.config.js file:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// tailwind.config.js</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">theme</span>: &#123;</span><br><span class="line">    <span class="attr">screens</span>: &#123;</span><br><span class="line">      <span class="string">&#x27;tablet&#x27;</span>: <span class="string">&#x27;640px&#x27;</span>,</span><br><span class="line">      <span class="comment">// =&gt; @media (min-width: 640px) &#123; ... &#125;</span></span><br><span class="line"></span><br><span class="line">      <span class="string">&#x27;laptop&#x27;</span>: <span class="string">&#x27;1024px&#x27;</span>,</span><br><span class="line">      <span class="comment">// =&gt; @media (min-width: 1024px) &#123; ... &#125;</span></span><br><span class="line"></span><br><span class="line">      <span class="string">&#x27;desktop&#x27;</span>: <span class="string">&#x27;1280px&#x27;</span>,</span><br><span class="line">      <span class="comment">// =&gt; @media (min-width: 1280px) &#123; ... &#125;</span></span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>Tailwind also supports many other common functions, such as dark mode, extraction components, custom function classes, etc. It also provides functions and instructions such as @apply. For specific docs, please refer to the following doc link.</p><p>Reference article:</p><ul><li><a href="https://www.dute.org/blog/what-is-postcss.html">一文搞懂什么是PostCSS</a></li><li><a href="https://www.tailwindcss.cn/docs/">TailwindCSS 中文文档</a></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;Tailwind this CSS framework is not something new, but has not been to study, recently there is a need to look at it, it looks relatively simple.&lt;/p&gt;
&lt;p&gt;This thing looks like a new DSL or something, providing many commonly used and built-in CSS styles, encapsulating them into syntax, and then providing a PostCSS plugin to process the encapsulated syntax back into ordinary CSS.&lt;/p&gt;
&lt;p&gt;All we need to do is install Tailwind’s PostCSS plugin and use his encapsulated DSL.&lt;/p&gt;</summary>
    
    
    
    <category term="CSS" scheme="https://sunra.top/en/categories/CSS/"/>
    
    
  </entry>
  
  <entry>
    <title>How to Develop a Relationship Graph with G6</title>
    <link href="https://sunra.top/en/posts/8324/"/>
    <id>https://sunra.top/en/posts/8324/</id>
    <published>2023-03-10T06:28:01.000Z</published>
    <updated>2026-06-13T06:03:37.123Z</updated>
    
    <content type="html"><![CDATA[<p>Recently, I was thinking about how to implement the relationship diagram of Feishu Docs, so I remembered the G6 I used before, so I simply implemented a version.</p><h1 id="final-effect"><a class="markdownIt-Anchor" href="#final-effect"></a> Final effect</h1><p>The main functions are as follows:</p><ul><li>The node is divided into two parts, the top half is the icon and the bottom half is the text<ul><li>When the mouse is placed on the icon, it will produce a diffusion effect of water ripples, and a circle of borders will appear at the same time</li><li>Text needs to be underlined and have a white background, and the water ripple effect cannot be blocked by the white background</li><li>The underline of the text needs to be a square</li></ul></li><li>The connection should have a gradual change of color, and the gradual change of color should be from the beginning of the arrow to the end of the arrow, and if the two-way relationship is supported, how to achieve two edges</li><li>There should be a Label in the middle of the connection</li><li>Nodes and connections should support translucency</li><li>The overall layout should be a force-oriented layout, and node dragging is supported. When dragging, nodes cannot overlap, but other nodes cannot be dragged due to connection (this point is raised separately because G6’s built-in force-oriented layout nodes will be dragged).</li></ul><span id="more"></span><h1 id="concrete-realization"><a class="markdownIt-Anchor" href="#concrete-realization"></a> Concrete realization</h1><h2 id="custom-node"><a class="markdownIt-Anchor" href="#custom-node"></a> Custom node</h2><p>The first difficulty of this Functional Button is:</p><ul><li>G6 Only keyShapre can respond to events, and the connection is connected to the keyShape injury, and the keyShape is the first shape of each group</li><li>So if we want the mouse to Hover the image to produce water ripples, we should make the image node the keyShape</li><li>But if we let image be keyShape, even if our picture is round, the box of keyShape is square, if the line is connected to the four corners of the image, there will be a little white space between the line and the picture, so we need to Let circle be keyShape, and then image is added later, but this will cause our keyShapre, that is, circle is covered by image, so that the hover event cannot be triggered</li></ul><p>There are two solutions, depending on whether the renderer you use is svg or canvas</p><ul><li><p>If it is canvas, let circle be keyShape, but add zIndex to both circle and image, and then call group.sort ()</p></li><li><p>If it is svg, group.sort is invalid, we need to change the hierarchy through the js method in the afterDraw method, and move the back circle to the front (the earlier you add it, the later it will be)</p></li></ul><p>The second difficulty is how to add the water ripple effect and how to turn on the water ripple when the Hover circle</p><p>The solution is divided into two steps:</p><ul><li>Use the water ripple code from the official example, but remember to set visible to false first, and pay attention to the hierarchy, so that the text is at the top</li><li>Then listen to the’node: mousemove ‘event, if the Hover target is circle, call setItemState, then when registering the node, set the setState callback, and then set visible to true through the shape.attr method, then listen to’node: mouseleave’, set the state to another, and set visible to false in the setState callback</li></ul><blockquote><p>The scheme of setting and listening to state changes can also be used to implement borders. Of course, this simple style can also be solved by stateStyle</p></blockquote><p>The third difficulty is how to add text underline and how to break lines if the text is too long, because the text in G6 does not support the underline I need</p><p>The solution is:</p><ul><li>Calculate the length of the text by yourself, break if it exceeds a certain length, delete and add ellipsis after more than two lines</li><li>Then add the path shape as an underscore below the text, and the length should be the text length.</li></ul><blockquote><p>Note that custom nodes should remember to inherit a built-in node, at least inherit single-node, otherwise many features are not available</p></blockquote><p>Here only shows the canvas code:</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">enum</span> <span class="title class_">ItemStatus</span> &#123;</span><br><span class="line">  <span class="variable constant_">OPACITY</span> = <span class="string">&#x27;opacity&#x27;</span>,</span><br><span class="line">  <span class="variable constant_">NORMAL</span> = <span class="string">&#x27;normal&#x27;</span>,</span><br><span class="line">  <span class="variable constant_">ACTIVE</span> = <span class="string">&#x27;active&#x27;</span>,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getLetterWidth</span>(<span class="params"><span class="attr">letter</span>: <span class="built_in">string</span>, <span class="attr">fontSize</span>: <span class="built_in">number</span></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> pattern = <span class="keyword">new</span> <span class="title class_">RegExp</span>(<span class="string">&#x27;[\u4E00-\u9FA5]+&#x27;</span>);</span><br><span class="line">  <span class="keyword">if</span> (pattern.<span class="title function_">test</span>(letter)) &#123;</span><br><span class="line">    <span class="comment">// Chinese charactors</span></span><br><span class="line">    <span class="keyword">return</span> fontSize;</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// get the width of single letter according to the fontSize</span></span><br><span class="line">    <span class="keyword">return</span> <span class="variable constant_">G6</span>.<span class="property">Util</span>.<span class="title function_">getLetterWidth</span>(letter, fontSize);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">getStringWidth</span>(<span class="params"><span class="attr">str</span>: <span class="built_in">string</span>, <span class="attr">fontSize</span>: <span class="built_in">number</span></span>) &#123;</span><br><span class="line">  <span class="keyword">let</span> currentWidth = <span class="number">0</span>;</span><br><span class="line">  str.<span class="title function_">split</span>(<span class="string">&#x27;&#x27;</span>).<span class="title function_">forEach</span>(<span class="function"><span class="params">letter</span> =&gt;</span> &#123;</span><br><span class="line">    currentWidth += <span class="title function_">getLetterWidth</span>(letter, fontSize);</span><br><span class="line">  &#125;);</span><br><span class="line">  <span class="keyword">return</span> currentWidth;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">replaceTooLongStringWithEllipsis</span>(<span class="params"></span></span><br><span class="line"><span class="params">  <span class="attr">strs</span>: <span class="built_in">string</span>[],</span></span><br><span class="line"><span class="params">  <span class="attr">maxWidth</span>: <span class="built_in">number</span>,</span></span><br><span class="line"><span class="params">  <span class="attr">fontSize</span>: <span class="built_in">number</span>,</span></span><br><span class="line"><span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> ellipsis = <span class="string">&#x27;...&#x27;</span>;</span><br><span class="line">  <span class="keyword">const</span> ellipsisLength = <span class="title function_">getStringWidth</span>(ellipsis, fontSize);</span><br><span class="line">  <span class="keyword">if</span> (strs.<span class="property">length</span> &gt; <span class="number">2</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> secondLine = strs[<span class="number">1</span>];</span><br><span class="line">    <span class="keyword">let</span> currentWidth = ellipsisLength;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; secondLine.<span class="property">length</span>; i++) &#123;</span><br><span class="line">      currentWidth += <span class="title function_">getLetterWidth</span>(secondLine[i], fontSize);</span><br><span class="line">      <span class="keyword">if</span> (currentWidth &gt;= maxWidth) &#123;</span><br><span class="line">        strs[<span class="number">1</span>] = <span class="string">`<span class="subst">$&#123;secondLine.slice(<span class="number">0</span>, i)&#125;</span><span class="subst">$&#123;ellipsis&#125;</span>`</span>;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> [strs[<span class="number">0</span>], strs[<span class="number">1</span>]];</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> strs;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">NODE_ICON_SIZE</span> = <span class="number">48</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">NODE_ICON_RADIUS</span> = <span class="variable constant_">NODE_ICON_SIZE</span> / <span class="number">2</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">NODE_NAME_FONT_SIZE</span> = <span class="number">14</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">NODE_NAME_HEIGHT</span> = <span class="number">18</span></span><br><span class="line"></span><br><span class="line"><span class="variable constant_">G6</span>.<span class="title function_">registerNode</span>(</span><br><span class="line">    <span class="string">&#x27;test-node&#x27;</span>,</span><br><span class="line">    &#123;</span><br><span class="line">      <span class="title function_">draw</span>(<span class="params">cfg, group</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> keyShape = group?.<span class="title function_">addShape</span>(<span class="string">&#x27;circle&#x27;</span>, &#123;</span><br><span class="line">          <span class="attr">attrs</span>: &#123;</span><br><span class="line">            <span class="attr">x</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">y</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">r</span>: <span class="variable constant_">NODE_ICON_RADIUS</span>,</span><br><span class="line">            <span class="attr">fill</span>: <span class="string">&#x27;rgba(255,255,255,0)&#x27;</span>,</span><br><span class="line">            <span class="attr">opacity</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">lineWidth</span>: <span class="number">1</span>,</span><br><span class="line">            <span class="attr">cursor</span>: <span class="string">&#x27;pointer&#x27;</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;test-node-dummy&#x27;</span>,</span><br><span class="line">          <span class="attr">draggle</span>: <span class="literal">true</span>,</span><br><span class="line">          <span class="attr">zIndex</span>: <span class="number">10</span>,</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        group?.<span class="title function_">addShape</span>(<span class="string">&#x27;image&#x27;</span>, &#123;</span><br><span class="line">          <span class="attr">attrs</span>: &#123;</span><br><span class="line">            <span class="attr">x</span>: -<span class="variable constant_">NODE_ICON_SIZE</span> / <span class="number">2</span>,</span><br><span class="line">            <span class="attr">y</span>: -<span class="variable constant_">NODE_ICON_SIZE</span> / <span class="number">2</span>,</span><br><span class="line">            <span class="attr">width</span>: <span class="variable constant_">NODE_ICON_SIZE</span>,</span><br><span class="line">            <span class="attr">height</span>: <span class="variable constant_">NODE_ICON_SIZE</span>,</span><br><span class="line">            <span class="attr">img</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">            <span class="attr">cursor</span>: <span class="string">&#x27;pointer&#x27;</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;test-node-icon&#x27;</span>,</span><br><span class="line">          <span class="attr">draggle</span>: <span class="literal">true</span>,</span><br><span class="line">          <span class="attr">zIndex</span>: <span class="number">9</span>,</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> lableSplit = <span class="title function_">fittingString</span>(</span><br><span class="line">          cfg?.<span class="property">supName</span> <span class="keyword">as</span> <span class="built_in">string</span>,</span><br><span class="line">          <span class="number">200</span>,</span><br><span class="line">          <span class="variable constant_">NODE_NAME_FONT_SIZE</span>,</span><br><span class="line">        );</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; lableSplit.<span class="property">length</span>; i++) &#123;</span><br><span class="line">            <span class="keyword">const</span> label = lableSplit[i];</span><br><span class="line">            <span class="keyword">const</span> labelWidth = <span class="title function_">getStringWidth</span>(</span><br><span class="line">                label,</span><br><span class="line">                <span class="variable constant_">NODE_NAME_FONT_SIZE</span>,</span><br><span class="line">            );</span><br><span class="line">            group?.<span class="title function_">addShape</span>(<span class="string">&#x27;rect&#x27;</span>, &#123;</span><br><span class="line">                <span class="attr">attrs</span>: &#123;</span><br><span class="line">                <span class="attr">x</span>: -labelWidth / <span class="number">2</span>,</span><br><span class="line">                <span class="attr">y</span>:</span><br><span class="line">                    <span class="variable constant_">NODE_ICON_SIZE</span> -</span><br><span class="line">                    <span class="variable constant_">NODE_NAME_HEIGHT</span> +</span><br><span class="line">                    i * <span class="variable constant_">NODE_NAME_HEIGHT</span> +</span><br><span class="line">                    <span class="number">4</span>,</span><br><span class="line">                <span class="attr">width</span>: labelWidth,</span><br><span class="line">                <span class="attr">height</span>: <span class="variable constant_">NODE_NAME_HEIGHT</span>,</span><br><span class="line">                <span class="attr">fill</span>: <span class="string">&#x27;#FFFFFF&#x27;</span>,</span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="attr">name</span>: <span class="string">`test-node-name-background-<span class="subst">$&#123;i&#125;</span>`</span>,</span><br><span class="line">                <span class="attr">zIndex</span>: <span class="number">3</span>,</span><br><span class="line">            &#125;);</span><br><span class="line"></span><br><span class="line">            group?.<span class="title function_">addShape</span>(<span class="string">&#x27;text&#x27;</span>, &#123;</span><br><span class="line">                <span class="attr">attrs</span>: &#123;</span><br><span class="line">                <span class="attr">text</span>: label,</span><br><span class="line">                <span class="attr">fill</span>: <span class="string">&#x27;#646A73&#x27;</span>,</span><br><span class="line">                <span class="attr">fontSize</span>: <span class="number">14</span>,</span><br><span class="line">                <span class="attr">textAlign</span>: <span class="string">&#x27;center&#x27;</span>,</span><br><span class="line">                <span class="attr">x</span>: <span class="number">0</span>,</span><br><span class="line">                <span class="attr">y</span>: <span class="variable constant_">NODE_ICON_SIZE</span> + i * <span class="variable constant_">NODE_NAME_HEIGHT</span>,</span><br><span class="line">                <span class="attr">width</span>: labelWidth,</span><br><span class="line">                <span class="attr">height</span>: <span class="variable constant_">NODE_NAME_HEIGHT</span>,</span><br><span class="line">                <span class="attr">cursor</span>: <span class="string">&#x27;pointer&#x27;</span>,</span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="attr">name</span>: <span class="string">`test-node-name-<span class="subst">$&#123;i&#125;</span>`</span>,</span><br><span class="line">                <span class="attr">zIndex</span>: <span class="number">3</span>,</span><br><span class="line">            &#125;);</span><br><span class="line"></span><br><span class="line">            group?.<span class="title function_">addShape</span>(<span class="string">&#x27;path&#x27;</span>, &#123;</span><br><span class="line">                <span class="attr">attrs</span>: &#123;</span><br><span class="line">                <span class="attr">path</span>: [</span><br><span class="line">                    [</span><br><span class="line">                    <span class="string">&#x27;M&#x27;</span>,</span><br><span class="line">                    -labelWidth / <span class="number">2</span>,</span><br><span class="line">                    <span class="variable constant_">NODE_ICON_SIZE</span> + i * <span class="variable constant_">NODE_NAME_HEIGHT</span> + <span class="number">2</span>,</span><br><span class="line">                    ],</span><br><span class="line">                    [</span><br><span class="line">                    <span class="string">&#x27;L&#x27;</span>,</span><br><span class="line">                    labelWidth / <span class="number">2</span>,</span><br><span class="line">                    <span class="variable constant_">NODE_ICON_SIZE</span> + i * <span class="variable constant_">NODE_NAME_HEIGHT</span> + <span class="number">2</span>,</span><br><span class="line">                    ],</span><br><span class="line">                ],</span><br><span class="line">                <span class="attr">stroke</span>: <span class="string">&#x27;#000000&#x27;</span>,</span><br><span class="line">                <span class="attr">lineWidth</span>: <span class="number">1</span>,</span><br><span class="line">                <span class="attr">lineDash</span>: [<span class="number">2</span>, <span class="number">2</span>],</span><br><span class="line">                &#125;,</span><br><span class="line">                <span class="attr">name</span>: <span class="string">`test-node-name-underline-<span class="subst">$&#123;i&#125;</span>`</span>,</span><br><span class="line">                <span class="attr">zIndex</span>: <span class="number">3</span>,</span><br><span class="line">            &#125;);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">const</span> back1 = group?.<span class="title function_">addShape</span>(<span class="string">&#x27;circle&#x27;</span>, &#123;</span><br><span class="line">          <span class="attr">zIndex</span>: <span class="number">5</span>,</span><br><span class="line">          <span class="attr">attrs</span>: &#123;</span><br><span class="line">            <span class="attr">x</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">y</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">r</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">fill</span>: <span class="string">&#x27;rgba(255,255,255,0)&#x27;</span>,</span><br><span class="line">            <span class="attr">opacity</span>: <span class="number">0</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;test-node-wave1&#x27;</span>,</span><br><span class="line">          <span class="attr">draggle</span>: <span class="literal">true</span>,</span><br><span class="line">        &#125;);</span><br><span class="line">        <span class="keyword">const</span> back2 = group?.<span class="title function_">addShape</span>(<span class="string">&#x27;circle&#x27;</span>, &#123;</span><br><span class="line">          <span class="attr">zIndex</span>: <span class="number">6</span>,</span><br><span class="line">          <span class="attr">attrs</span>: &#123;</span><br><span class="line">            <span class="attr">x</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">y</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">r</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">fill</span>: <span class="string">&#x27;rgba(255,255,255,0)&#x27;</span>,</span><br><span class="line">            <span class="attr">opacity</span>: <span class="number">0</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;test-node-wave2&#x27;</span>,</span><br><span class="line">          <span class="attr">draggle</span>: <span class="literal">true</span>,</span><br><span class="line">        &#125;);</span><br><span class="line">        <span class="keyword">const</span> back3 = group?.<span class="title function_">addShape</span>(<span class="string">&#x27;circle&#x27;</span>, &#123;</span><br><span class="line">          <span class="attr">zIndex</span>: <span class="number">7</span>,</span><br><span class="line">          <span class="attr">attrs</span>: &#123;</span><br><span class="line">            <span class="attr">x</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">y</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">r</span>: <span class="number">0</span>,</span><br><span class="line">            <span class="attr">fill</span>: <span class="string">&#x27;rgba(255,255,255,0)&#x27;</span>,</span><br><span class="line">            <span class="attr">opacity</span>: <span class="number">0</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">          <span class="attr">name</span>: <span class="string">&#x27;test-node-wave3&#x27;</span>,</span><br><span class="line">          <span class="attr">draggle</span>: <span class="literal">true</span>,</span><br><span class="line">        &#125;);</span><br><span class="line"></span><br><span class="line">        back1?.<span class="title function_">animate</span>(</span><br><span class="line">          &#123;</span><br><span class="line">            <span class="comment">// Magnifying and disappearing</span></span><br><span class="line">            <span class="attr">r</span>: <span class="variable constant_">NODE_ICON_RADIUS</span> + <span class="number">16</span>,</span><br><span class="line">            <span class="attr">opacity</span>: <span class="number">0.1</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">          &#123;</span><br><span class="line">            <span class="attr">duration</span>: <span class="number">3000</span>,</span><br><span class="line">            <span class="attr">easing</span>: <span class="string">&#x27;easeCubic&#x27;</span>,</span><br><span class="line">            <span class="attr">delay</span>: <span class="number">100</span>,</span><br><span class="line">            <span class="attr">repeat</span>: <span class="literal">true</span>, <span class="comment">// repeat</span></span><br><span class="line">          &#125;,</span><br><span class="line">        ); <span class="comment">// no delay</span></span><br><span class="line">        back2?.<span class="title function_">animate</span>(</span><br><span class="line">          &#123;</span><br><span class="line">            <span class="comment">// Magnifying and disappearing</span></span><br><span class="line">            <span class="attr">r</span>: <span class="variable constant_">NODE_ICON_RADIUS</span> + <span class="number">16</span>,</span><br><span class="line">            <span class="attr">opacity</span>: <span class="number">0.1</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">          &#123;</span><br><span class="line">            <span class="attr">duration</span>: <span class="number">3000</span>,</span><br><span class="line">            <span class="attr">easing</span>: <span class="string">&#x27;easeCubic&#x27;</span>,</span><br><span class="line">            <span class="attr">delay</span>: <span class="number">1000</span>,</span><br><span class="line">            <span class="attr">repeat</span>: <span class="literal">true</span>, <span class="comment">// repeat</span></span><br><span class="line">          &#125;,</span><br><span class="line">        ); <span class="comment">// 1s delay</span></span><br><span class="line">        back3?.<span class="title function_">animate</span>(</span><br><span class="line">          &#123;</span><br><span class="line">            <span class="comment">// Magnifying and disappearing</span></span><br><span class="line">            <span class="attr">r</span>: <span class="variable constant_">NODE_ICON_RADIUS</span> + <span class="number">16</span>,</span><br><span class="line">            <span class="attr">opacity</span>: <span class="number">0.1</span>,</span><br><span class="line">          &#125;,</span><br><span class="line">          &#123;</span><br><span class="line">            <span class="attr">duration</span>: <span class="number">3000</span>,</span><br><span class="line">            <span class="attr">easing</span>: <span class="string">&#x27;easeCubic&#x27;</span>,</span><br><span class="line">            <span class="attr">delay</span>: <span class="number">2000</span>,</span><br><span class="line">            <span class="attr">repeat</span>: <span class="literal">true</span>, <span class="comment">// repeat</span></span><br><span class="line">          &#125;,</span><br><span class="line">        ); <span class="comment">// 3s delay</span></span><br><span class="line"></span><br><span class="line">        back1?.<span class="title function_">hide</span>();</span><br><span class="line">        back2?.<span class="title function_">hide</span>();</span><br><span class="line">        back3?.<span class="title function_">hide</span>();</span><br><span class="line"></span><br><span class="line">        group?.<span class="title function_">sort</span>();</span><br><span class="line">        <span class="keyword">return</span> keyShape <span class="keyword">as</span> <span class="title class_">IShape</span>;</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="title function_">setState</span>(<span class="params">name, value, item</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (name = <span class="string">&#x27;status&#x27;</span>) &#123;</span><br><span class="line">          <span class="keyword">if</span> (value = <span class="title class_">ItemStatus</span>.<span class="property">ACTIVE</span>) &#123;</span><br><span class="line">            <span class="keyword">const</span> group = item?.<span class="title function_">getContainer</span>();</span><br><span class="line">            <span class="keyword">const</span> shapes = group?.<span class="title function_">getChildren</span>() ?? [];</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">const</span> shape <span class="keyword">of</span> shapes) &#123;</span><br><span class="line">              <span class="keyword">if</span> (shape.<span class="property">cfg</span>.<span class="property">name</span>?.<span class="title function_">includes</span>(<span class="string">&#x27;test-node-wave&#x27;</span>)) &#123;</span><br><span class="line">                shape.<span class="title function_">attr</span>(<span class="string">&#x27;opacity&#x27;</span>, <span class="number">0.6</span>);</span><br><span class="line">                shape.<span class="title function_">attr</span>(<span class="string">&#x27;fill&#x27;</span>, <span class="string">&#x27;#4E83FD&#x27;</span>);</span><br><span class="line">                shape.<span class="title function_">show</span>();</span><br><span class="line">              &#125; <span class="keyword">else</span> <span class="keyword">if</span> (shape.<span class="property">cfg</span>.<span class="property">name</span>?.<span class="title function_">includes</span>(<span class="string">&#x27;test-node-dummy&#x27;</span>)) &#123;</span><br><span class="line">                shape.<span class="title function_">attr</span>(<span class="string">&#x27;opacity&#x27;</span>, <span class="number">1</span>);</span><br><span class="line">                shape.<span class="title function_">attr</span>(<span class="string">&#x27;stroke&#x27;</span>, <span class="string">&#x27;#4E83FD&#x27;</span>);</span><br><span class="line">              &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                shape.<span class="title function_">attr</span>(<span class="string">&#x27;opacity&#x27;</span>, <span class="number">1</span>);</span><br><span class="line">              &#125;</span><br><span class="line">            &#125;</span><br><span class="line">          &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">const</span> group = item?.<span class="title function_">getContainer</span>();</span><br><span class="line">            <span class="keyword">const</span> shapes = group?.<span class="title function_">getChildren</span>() ?? [];</span><br><span class="line">            <span class="keyword">for</span> (<span class="keyword">const</span> shape <span class="keyword">of</span> shapes) &#123;</span><br><span class="line">              <span class="keyword">if</span> (shape.<span class="property">cfg</span>.<span class="property">name</span>?.<span class="title function_">includes</span>(<span class="string">&#x27;test-node-wave&#x27;</span>)) &#123;</span><br><span class="line">                shape.<span class="title function_">attr</span>(<span class="string">&#x27;opacity&#x27;</span>, <span class="number">0</span>);</span><br><span class="line">                shape.<span class="title function_">attr</span>(<span class="string">&#x27;fill&#x27;</span>, <span class="string">&#x27;#FFFFFF&#x27;</span>);</span><br><span class="line">                shape.<span class="title function_">hide</span>();</span><br><span class="line">              &#125; <span class="keyword">else</span> <span class="keyword">if</span> (shape.<span class="property">cfg</span>.<span class="property">name</span>?.<span class="title function_">includes</span>(<span class="string">&#x27;test-node-dummy&#x27;</span>)) &#123;</span><br><span class="line">                shape.<span class="title function_">attr</span>(<span class="string">&#x27;opacity&#x27;</span>, <span class="number">0</span>);</span><br><span class="line">                shape.<span class="title function_">attr</span>(<span class="string">&#x27;stroke&#x27;</span>, <span class="string">&#x27;#FFFFFF&#x27;</span>);</span><br><span class="line">              &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">                shape.<span class="title function_">attr</span>(<span class="string">&#x27;opacity&#x27;</span>, value = <span class="title class_">ItemStatus</span>.<span class="property">OPACITY</span> ? <span class="number">0.2</span> : <span class="number">1</span>);</span><br><span class="line">              &#125;</span><br><span class="line">            &#125;</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&#x27;single-node&#x27;</span>,</span><br><span class="line">  );</span><br></pre></td></tr></table></figure><h2 id="connection"><a class="markdownIt-Anchor" href="#connection"></a> Connection</h2><p>The first difficulty is that you can’t simply add a lable to draw or afterdraw. This only applies to the situation where the relative position of the text and the starting point of the line remains unchanged. When we need it, the node can be dragged and dropped, which means that the length of the line can be changed, and what we require is that the text is in the middle of the line.</p><p>The solution is:</p><ul><li>Remove the previous added text shape and add new text shape every time in afterUpdate</li><li>There is actually no group in afterUpdate. You can forcibly mount group to cfg after draw.</li></ul><p>The second difficulty is that how to keep the gradual change of color must be from the starting point to the end point of the connection, because G6 only supports the setting of a fixed angle, such as setting a gradual change of 0 degrees, it must be a gradual change from left to right, if A line is from right to left, then this gradual change of color is reversed</p><p>The solution is:</p><ul><li>Or in afterUpdate, constantly calculate the position of the new startPoint and endPoint to calculate the angle</li><li>Set the gradual change color attribute of stroke by calculating the angle and then using shape.attr</li></ul><p>The third difficulty is how to support bilinear curves, because the default is a straight line, and the two-way lines will overlap</p><p>The solution lies in:</p><ul><li>Define another custom type, based on Bezier curve extension</li></ul><p>The specific code is as follows:</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="variable constant_">EDGE_LABEL_HEIGHT</span> = <span class="number">18</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">EDGE_LABEL_FONT_SIZE</span> = <span class="number">10</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">addLabelToEdge</span>(<span class="params"><span class="attr">cfg</span>: <span class="title class_">ModelConfig</span> | <span class="literal">undefined</span></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> config = cfg <span class="keyword">as</span> <span class="title class_">ModelConfig</span>;</span><br><span class="line">  <span class="keyword">const</span> group = cfg?.<span class="property">group</span> <span class="keyword">as</span> <span class="title class_">IGroup</span>;</span><br><span class="line">  <span class="keyword">const</span> shape = group?.<span class="title function_">get</span>(<span class="string">&#x27;children&#x27;</span>)[<span class="number">0</span>];</span><br><span class="line">  <span class="comment">// get the coordinate of the mid point on the path</span></span><br><span class="line">  <span class="comment">//Get the coordinates of the midpoint of the path graph</span></span><br><span class="line">  <span class="keyword">const</span> midPoint = shape.<span class="title function_">getPoint</span>(<span class="number">0.5</span>);</span><br><span class="line">  <span class="keyword">const</span> startPoint = cfg?.<span class="property">startPoint</span>;</span><br><span class="line">  <span class="keyword">const</span> endPoint = cfg?.<span class="property">endPoint</span>;</span><br><span class="line">  <span class="keyword">if</span> (startPoint &amp;&amp; endPoint) &#123;</span><br><span class="line">    <span class="keyword">const</span> angle =</span><br><span class="line">      <span class="title class_">Math</span>.<span class="title function_">atan2</span>(endPoint.<span class="property">y</span> - startPoint.<span class="property">y</span>, endPoint.<span class="property">x</span> - startPoint.<span class="property">x</span>) * <span class="number">2</span>;</span><br><span class="line">    <span class="keyword">if</span> (angle &gt; -<span class="title class_">Math</span>.<span class="property">PI</span> &amp;&amp; angle &lt; <span class="title class_">Math</span>.<span class="property">PI</span>) &#123;</span><br><span class="line">      shape.<span class="title function_">attr</span>(<span class="string">&#x27;stroke&#x27;</span>, <span class="string">`l(0) 0:#4E83FD 1:#B6CBFE`</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      shape.<span class="title function_">attr</span>(<span class="string">&#x27;stroke&#x27;</span>, <span class="string">`l(0) 0:#B6CBFE 1:#4E83FD`</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> (midPoint) &#123;</span><br><span class="line">    <span class="keyword">const</span> labelWidth = <span class="title function_">getStringWidth</span>(</span><br><span class="line">      config.<span class="property">text</span> <span class="keyword">as</span> <span class="built_in">string</span>,</span><br><span class="line">      <span class="variable constant_">EDGE_LABEL_FONT_SIZE</span>,</span><br><span class="line">    );</span><br><span class="line">    group?.<span class="title function_">removeChild</span>(config.<span class="property">preEdgeText</span> <span class="keyword">as</span> <span class="built_in">any</span>);</span><br><span class="line">    group?.<span class="title function_">removeChild</span>(config.<span class="property">preEdgeTextBackground</span> <span class="keyword">as</span> <span class="built_in">any</span>);</span><br><span class="line">    config.<span class="property">preEdgeTextBackground</span> = group.<span class="title function_">addShape</span>(<span class="string">&#x27;rect&#x27;</span>, &#123;</span><br><span class="line">      <span class="attr">attrs</span>: &#123;</span><br><span class="line">        <span class="attr">x</span>: midPoint.<span class="property">x</span> - (labelWidth + <span class="number">12</span>) / <span class="number">2</span>,</span><br><span class="line">        <span class="attr">y</span>: midPoint.<span class="property">y</span> - <span class="variable constant_">EDGE_LABEL_HEIGHT</span> + <span class="number">4</span>,</span><br><span class="line">        <span class="attr">width</span>: labelWidth + <span class="number">12</span>,</span><br><span class="line">        <span class="attr">height</span>: <span class="variable constant_">EDGE_LABEL_HEIGHT</span>,</span><br><span class="line">        <span class="attr">fill</span>: <span class="string">&#x27;#E1EAFF&#x27;</span>,</span><br><span class="line">        <span class="attr">radius</span>: <span class="variable constant_">EDGE_LABEL_HEIGHT</span> / <span class="number">2</span>,</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&#x27;test-edge-background&#x27;</span>,</span><br><span class="line">    &#125;);</span><br><span class="line">    config.<span class="property">preEdgeText</span> = group.<span class="title function_">addShape</span>(<span class="string">&#x27;text&#x27;</span>, &#123;</span><br><span class="line">      <span class="attr">attrs</span>: &#123;</span><br><span class="line">        <span class="attr">text</span>: cfg?.<span class="property">text</span>,</span><br><span class="line">        <span class="attr">fill</span>: <span class="string">&#x27;#3370FF&#x27;</span>,</span><br><span class="line">        <span class="attr">fontWeight</span>: <span class="number">500</span>,</span><br><span class="line">        <span class="attr">fontSize</span>: <span class="number">10</span>,</span><br><span class="line">        <span class="attr">lineHeight</span>: <span class="number">16</span>,</span><br><span class="line">        <span class="attr">textAlign</span>: <span class="string">&#x27;center&#x27;</span>,</span><br><span class="line">        <span class="attr">x</span>: midPoint.<span class="property">x</span>,</span><br><span class="line">        <span class="attr">y</span>: midPoint.<span class="property">y</span>,</span><br><span class="line">        <span class="attr">width</span>: labelWidth + <span class="number">12</span>,</span><br><span class="line">        <span class="attr">height</span>: <span class="variable constant_">EDGE_LABEL_HEIGHT</span>,</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&#x27;test-edge-text&#x27;</span>,</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="variable constant_">G6</span>.<span class="title function_">registerEdge</span>(</span><br><span class="line"><span class="string">&#x27;test-edge-single&#x27;</span>,</span><br><span class="line">&#123;</span><br><span class="line">    <span class="title function_">afterDraw</span>(<span class="params">cfg, group</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> config = cfg <span class="keyword">as</span> <span class="title class_">ModelConfig</span>;</span><br><span class="line">    config.<span class="property">group</span> = group;</span><br><span class="line">    <span class="title function_">addLabelToEdge</span>(cfg);</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">afterUpdate</span>(<span class="params">cfg</span>) &#123;</span><br><span class="line">    <span class="title function_">addLabelToEdge</span>(cfg);</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;,</span><br><span class="line"><span class="string">&#x27;line&#x27;</span>,</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="variable constant_">G6</span>.<span class="title function_">registerEdge</span>(</span><br><span class="line"><span class="string">&#x27;test-edge-double&#x27;</span>,</span><br><span class="line">&#123;</span><br><span class="line">    <span class="title function_">afterDraw</span>(<span class="params">cfg, group</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> config = cfg <span class="keyword">as</span> <span class="title class_">ModelConfig</span>;</span><br><span class="line">    config.<span class="property">group</span> = group;</span><br><span class="line">    <span class="title function_">addLabelToEdge</span>(cfg);</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">afterUpdate</span>(<span class="params">cfg</span>) &#123;</span><br><span class="line">    <span class="title function_">addLabelToEdge</span>(cfg);</span><br><span class="line">    &#125;,</span><br><span class="line">&#125;,</span><br><span class="line"><span class="string">&#x27;quadratic&#x27;</span>,</span><br><span class="line">);</span><br></pre></td></tr></table></figure><h2 id="event-monitoring-changes-node-and-connection-styles"><a class="markdownIt-Anchor" href="#event-monitoring-changes-node-and-connection-styles"></a> Event monitoring changes node and connection styles</h2><p>Code for event monitoring:</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">highlightLocalNodesAndEdges</span>(<span class="params"><span class="attr">graphInstance</span>: <span class="title class_">IGraph</span>, <span class="attr">e</span>: <span class="title class_">IG6GraphEvent</span></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> &#123; localEdges, localNodesId, otherNodesId, otherEdges &#125; =</span><br><span class="line">    <span class="title function_">getAllLocalNodesAndEdges</span>(graphInstance, e.<span class="property">item</span>?.<span class="title function_">getModel</span>().<span class="property">id</span> <span class="keyword">as</span> <span class="built_in">string</span>);</span><br><span class="line"></span><br><span class="line">  localEdges.<span class="title function_">forEach</span>(<span class="function"><span class="params">edge</span> =&gt;</span> &#123;</span><br><span class="line">    graphInstance.<span class="title function_">setItemState</span>(</span><br><span class="line">      edge.<span class="title function_">getModel</span>().<span class="property">id</span> <span class="keyword">as</span> <span class="built_in">string</span>,</span><br><span class="line">      <span class="string">&#x27;status&#x27;</span>,</span><br><span class="line">      <span class="title class_">ItemStatus</span>.<span class="property">NORMAL</span>,</span><br><span class="line">    );</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  otherEdges.<span class="title function_">forEach</span>(<span class="function"><span class="params">edge</span> =&gt;</span> &#123;</span><br><span class="line">    graphInstance.<span class="title function_">setItemState</span>(</span><br><span class="line">      edge.<span class="title function_">getModel</span>().<span class="property">id</span> <span class="keyword">as</span> <span class="built_in">string</span>,</span><br><span class="line">      <span class="string">&#x27;status&#x27;</span>,</span><br><span class="line">      <span class="title class_">ItemStatus</span>.<span class="property">OPACITY</span>,</span><br><span class="line">    );</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  localNodesId.<span class="title function_">forEach</span>(<span class="function"><span class="params">nodeId</span> =&gt;</span> &#123;</span><br><span class="line">    graphInstance.<span class="title function_">setItemState</span>(nodeId <span class="keyword">as</span> <span class="built_in">string</span>, <span class="string">&#x27;status&#x27;</span>, <span class="title class_">ItemStatus</span>.<span class="property">NORMAL</span>);</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  otherNodesId.<span class="title function_">forEach</span>(<span class="function"><span class="params">nodeId</span> =&gt;</span> &#123;</span><br><span class="line">    graphInstance.<span class="title function_">setItemState</span>(nodeId <span class="keyword">as</span> <span class="built_in">string</span>, <span class="string">&#x27;status&#x27;</span>, <span class="title class_">ItemStatus</span>.<span class="property">OPACITY</span>);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">highlightAllNodesAndGraph</span>(<span class="params"><span class="attr">graphInstance</span>: <span class="title class_">IGraph</span></span>) &#123;</span><br><span class="line">  graphInstance.<span class="title function_">findAll</span>(<span class="string">&#x27;edge&#x27;</span>, <span class="function"><span class="params">edge</span> =&gt;</span> &#123;</span><br><span class="line">    graphInstance.<span class="title function_">setItemState</span>(edge, <span class="string">&#x27;status&#x27;</span>, <span class="title class_">ItemStatus</span>.<span class="property">NORMAL</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line">  graphInstance.<span class="title function_">findAll</span>(<span class="string">&#x27;node&#x27;</span>, <span class="function"><span class="params">node</span> =&gt;</span> &#123;</span><br><span class="line">    graphInstance.<span class="title function_">setItemState</span>(node, <span class="string">&#x27;status&#x27;</span>, <span class="title class_">ItemStatus</span>.<span class="property">NORMAL</span>);</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">useInternalEventListener</span>(<span class="params"><span class="attr">graphInstance</span>: <span class="title class_">IGraph</span> | <span class="literal">null</span></span>) &#123;</span><br><span class="line">  <span class="title function_">useEffect</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">onMouseMoveOnNode</span>(<span class="params"><span class="attr">e</span>: <span class="title class_">IG6GraphEvent</span></span>) &#123;</span><br><span class="line">      <span class="keyword">if</span> (</span><br><span class="line">        !e.<span class="property">target</span>.<span class="property">cfg</span>.<span class="property">name</span>?.<span class="title function_">includes</span>(<span class="string">&#x27;test-node--name-&#x27;</span>) &amp;&amp;</span><br><span class="line">        graphInstance</span><br><span class="line">      ) &#123;</span><br><span class="line">        <span class="title function_">highlightLocalNodesAndEdges</span>(graphInstance, e);</span><br><span class="line">        graphInstance.<span class="title function_">setItemState</span>(e.<span class="property">item</span> <span class="keyword">as</span> <span class="title class_">Item</span>, <span class="string">&#x27;status&#x27;</span>, <span class="title class_">ItemStatus</span>.<span class="property">ACTIVE</span>);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">function</span> <span class="title function_">onMouseLeaveNode</span>(<span class="params"></span>) &#123;</span><br><span class="line">      <span class="keyword">if</span> (graphInstance) &#123;</span><br><span class="line">        <span class="title function_">highlightAllNodesAndGraph</span>(graphInstance);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    graphInstance?.<span class="title function_">on</span>(<span class="string">&#x27;node:mousemove&#x27;</span>, onMouseMoveOnNode);</span><br><span class="line"></span><br><span class="line">    graphInstance?.<span class="title function_">on</span>(<span class="string">&#x27;node:mouseleave&#x27;</span>, onMouseLeaveNode);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="function">() =&gt;</span> &#123;</span><br><span class="line">      graphInstance?.<span class="title function_">off</span>(<span class="string">&#x27;node:mousemove&#x27;</span>, onMouseMoveOnNode);</span><br><span class="line"></span><br><span class="line">      graphInstance?.<span class="title function_">off</span>(<span class="string">&#x27;node:mouseleave&#x27;</span>, onMouseLeaveNode);</span><br><span class="line">    &#125;;</span><br><span class="line">  &#125;, [graphInstance]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="layout-algorithms-and-drag-nodes"><a class="markdownIt-Anchor" href="#layout-algorithms-and-drag-nodes"></a> Layout algorithms and drag nodes</h2><p>G6 actually comes with a force-oriented layout, but it’s weird, the effect is different from d3, and it doesn’t support only collision detection when dragging</p><p>There are a few difficulties here:</p><ul><li>How to use force-oriented layout of d3, here mainly d3 will change the data structure of points, causing G6 to execute abnormally</li><li>If you implement collision detection yourself</li><li>How to smooth a bit when dragging nodes</li></ul><p>The solution is as follows:</p><ul><li>Use Promise to encapsulate the layout algorithm of d3, process the data into the format supported by G6 after monitoring the end event, otherwise let G6 render without waiting for all ticks to be completed. Halfway through, d3 changes the data format again, an error will be reported</li><li>Self-implemented collision detection is actually a simple way to determine the distance between nodes. If it is less than a certain value, push other nodes away, then record the nodes that are pushed away, and calculate the distance between the nodes that are pushed away and all nodes., if there is still close, modify the position and continue the recursion of the nodes that modify the position in this round. In order to prevent stack overflow, you can set the maximum recursion layer of 30</li><li>If the refreshPosition method is called after each node is calculated, it will actually cause line shaking. The solution is to enable force layout, so layout can be used to achieve smooth re-rendering, but the positions of all nodes are set with fx and fy to prevent force-oriented layout from modifying position</li></ul><p>The code is as follows:</p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="variable constant_">REFRESH_NODE_POSITION_RECURSION_COUNT</span> = <span class="number">30</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">REFRESH_NODE_COLLIDE_RADIUS</span> = <span class="number">150</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">REFRESH_NODE_COLLIDE_RADIUS_SEQUARE</span> = <span class="title class_">Math</span>.<span class="title function_">pow</span>(</span><br><span class="line">  <span class="variable constant_">REFRESH_NODE_COLLIDE_RADIUS</span>,</span><br><span class="line">  <span class="number">2</span>,</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">getTwoNodeDistance</span>(<span class="params"><span class="attr">node1</span>: <span class="title class_">NodeConfig</span>, <span class="attr">node2</span>: <span class="title class_">NodeConfig</span></span>) &#123;</span><br><span class="line">  <span class="keyword">const</span> distance =</span><br><span class="line">    <span class="title class_">Math</span>.<span class="title function_">pow</span>((node1.<span class="property">x</span> <span class="keyword">as</span> <span class="built_in">number</span>) - (node2.<span class="property">x</span> <span class="keyword">as</span> <span class="built_in">number</span>), <span class="number">2</span>) +</span><br><span class="line">    <span class="title class_">Math</span>.<span class="title function_">pow</span>((node1.<span class="property">y</span> <span class="keyword">as</span> <span class="built_in">number</span>) - (node2.<span class="property">y</span> <span class="keyword">as</span> <span class="built_in">number</span>), <span class="number">2</span>);</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Math</span>.<span class="title function_">sqrt</span>(distance);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">refreshNodesPositionHelper</span>(<span class="params"></span></span><br><span class="line"><span class="params">  <span class="attr">dragedNode</span>: <span class="title class_">NodeConfig</span>,</span></span><br><span class="line"><span class="params">  <span class="attr">positionChangedNodes</span>: <span class="title class_">NodeConfig</span>[],</span></span><br><span class="line"><span class="params">  <span class="attr">allNodes</span>: <span class="title class_">NodeConfig</span>[],</span></span><br><span class="line"><span class="params">  deep = <span class="number">0</span>,</span></span><br><span class="line"><span class="params"></span>) &#123;</span><br><span class="line">  <span class="keyword">if</span> (deep &gt; <span class="variable constant_">REFRESH_NODE_POSITION_RECURSION_COUNT</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">const</span> nextPositionChangedNodesSet = <span class="keyword">new</span> <span class="title class_">Set</span>&lt;<span class="title class_">NodeConfig</span>&gt;();</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">const</span> positionChangedNode <span class="keyword">of</span> positionChangedNodes) &#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">const</span> everyNode <span class="keyword">of</span> allNodes) &#123;</span><br><span class="line">      <span class="keyword">if</span> (positionChangedNode.<span class="property">id</span> = everyNode.<span class="property">id</span>) &#123;</span><br><span class="line">        <span class="keyword">continue</span>;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">const</span> distance = <span class="title function_">getTwoNodeDistance</span>(positionChangedNode, everyNode);</span><br><span class="line">      <span class="keyword">if</span> (distance &lt; <span class="variable constant_">REFRESH_NODE_COLLIDE_RADIUS</span>) &#123;</span><br><span class="line">        nextPositionChangedNodesSet.<span class="title function_">add</span>(everyNode);</span><br><span class="line">        <span class="keyword">const</span> detaX = <span class="title class_">Math</span>.<span class="title function_">abs</span>(</span><br><span class="line">          (positionChangedNode.<span class="property">x</span> <span class="keyword">as</span> <span class="built_in">number</span>) - (everyNode.<span class="property">x</span> <span class="keyword">as</span> <span class="built_in">number</span>),</span><br><span class="line">        );</span><br><span class="line">        <span class="keyword">const</span> detaY = <span class="title class_">Math</span>.<span class="property">abs</span> (</span><br><span class="line">          (positionChangedNode.<span class="property">y</span> <span class="keyword">as</span> <span class="built_in">number</span>) - (everyNode.<span class="property">y</span> <span class="keyword">as</span> <span class="built_in">number</span>),</span><br><span class="line">        );</span><br><span class="line"></span><br><span class="line">        <span class="comment">//Root formula for quadratic equation system of one yuan 2 * moveDistance ^ 2 + 2 (detaX + detaY) * moveDistance = REFRESH_NODE_COLLIDE_RADIUS_SEQUARE - (detaX ^ 2 + detaY ^ 2)</span></span><br><span class="line">        <span class="keyword">const</span> a = <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">const</span> b = <span class="number">2</span> * (detaX + detaY);</span><br><span class="line">        <span class="keyword">const</span> c =</span><br><span class="line">          detaX * detaX + detaY * detaY - <span class="variable constant_">REFRESH_NODE_COLLIDE_RADIUS_SEQUARE</span>;</span><br><span class="line">        <span class="keyword">const</span> moveDistance = (<span class="title class_">Math</span>.<span class="title function_">sqrt</span>(b * b - <span class="number">4</span> * a * c) - b) / (<span class="number">2</span> * a);</span><br><span class="line"></span><br><span class="line">        everyNode.<span class="property">x</span> =</span><br><span class="line">          (everyNode.<span class="property">x</span> <span class="keyword">as</span> <span class="built_in">number</span>) +</span><br><span class="line">          ((everyNode.<span class="property">x</span> <span class="keyword">as</span> <span class="built_in">number</span>) - (positionChangedNode.<span class="property">x</span> <span class="keyword">as</span> <span class="built_in">number</span>) &gt; <span class="number">0</span></span><br><span class="line">            ? <span class="number">1</span></span><br><span class="line">            : -<span class="number">1</span>) *</span><br><span class="line">            moveDistance;</span><br><span class="line"></span><br><span class="line">        everyNode.<span class="property">y</span> =</span><br><span class="line">          (everyNode.<span class="property">y</span> <span class="keyword">as</span> <span class="built_in">number</span>) +</span><br><span class="line">          ((everyNode.<span class="property">y</span> <span class="keyword">as</span> <span class="built_in">number</span>) - (positionChangedNode.<span class="property">y</span> <span class="keyword">as</span> <span class="built_in">number</span>) &gt; <span class="number">0</span></span><br><span class="line">            ? <span class="number">1</span></span><br><span class="line">            : -<span class="number">1</span>) *</span><br><span class="line">            moveDistance;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">if</span> (nextPositionChangedNodesSet.<span class="property">size</span> &gt; <span class="number">0</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> <span class="attr">nextPositionChangedNodes</span>: <span class="title class_">NodeConfig</span>[] = [];</span><br><span class="line">    nextPositionChangedNodesSet.<span class="title function_">forEach</span>(<span class="function"><span class="params">value</span> =&gt;</span> &#123;</span><br><span class="line">      nextPositionChangedNodes.<span class="title function_">push</span>(value);</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="title function_">refreshNodesPositionHelper</span>(</span><br><span class="line">      dragedNode,</span><br><span class="line">      nextPositionChangedNodes,</span><br><span class="line">      allNodes,</span><br><span class="line">      deep + <span class="number">1</span>,</span><br><span class="line">    );</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    allNodes.<span class="title function_">forEach</span>(<span class="function"><span class="params">node</span> =&gt;</span> &#123;</span><br><span class="line">      node.<span class="property">fx</span> = node.<span class="property">x</span>;</span><br><span class="line">      node.<span class="property">fy</span> = node.<span class="property">y</span>;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">onNodeDrag</span>(<span class="params"><span class="attr">e</span>: <span class="title class_">IG6GraphEvent</span></span>) &#123;</span><br><span class="line">    graphInstance?.<span class="title function_">layout</span>();</span><br><span class="line">    <span class="keyword">const</span> model = e.<span class="property">item</span>?.<span class="title function_">get</span>(<span class="string">&#x27;model&#x27;</span>);</span><br><span class="line">    model.<span class="property">x</span> = e.<span class="property">x</span>;</span><br><span class="line">    model.<span class="property">y</span> = e.<span class="property">y</span>;</span><br><span class="line">    model.<span class="property">fx</span> = e.<span class="property">x</span>;</span><br><span class="line">    model.<span class="property">fy</span> = e.<span class="property">y</span>;</span><br><span class="line">    <span class="keyword">const</span> allNodes = graphInstance</span><br><span class="line">    ?.<span class="title function_">findAll</span>(<span class="string">&#x27;node&#x27;</span>, <span class="function"><span class="params">node</span> =&gt;</span> node.<span class="title function_">getID</span>() ! e.<span class="property">item</span>?.<span class="title function_">getID</span>())</span><br><span class="line">    .<span class="title function_">map</span>(<span class="function"><span class="params">node</span> =&gt;</span> node.<span class="title function_">getModel</span>()) <span class="keyword">as</span> <span class="title class_">NodeConfig</span>[];</span><br><span class="line"></span><br><span class="line">    <span class="title function_">refreshNodesPositionHelper</span>(model, [model], allNodes);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">onMouseMoveOnNode</span>(<span class="params"><span class="attr">e</span>: <span class="title class_">IG6GraphEvent</span></span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (</span><br><span class="line">    !e.<span class="property">target</span>.<span class="property">cfg</span>.<span class="property">name</span>?.<span class="title function_">includes</span>(<span class="string">&#x27;test-node--name-&#x27;</span>) &amp;&amp;</span><br><span class="line">    graphInstance</span><br><span class="line">    ) &#123;</span><br><span class="line">    <span class="title function_">highlightLocalNodesAndEdges</span>(graphInstance, e);</span><br><span class="line">    graphInstance.<span class="title function_">setItemState</span>(e.<span class="property">item</span> <span class="keyword">as</span> <span class="title class_">Item</span>, <span class="string">&#x27;status&#x27;</span>, <span class="title class_">ItemStatus</span>.<span class="property">ACTIVE</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">onMouseLeaveNode</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (graphInstance) &#123;</span><br><span class="line">    <span class="title function_">highlightAllNodesAndGraph</span>(graphInstance);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">graphInstance?.<span class="title function_">on</span>(<span class="string">&#x27;node:drag&#x27;</span>, onNodeDrag);</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;Recently, I was thinking about how to implement the relationship diagram of Feishu Docs, so I remembered the G6 I used before, so I simply implemented a version.&lt;/p&gt;
&lt;h1 id=&quot;final-effect&quot;&gt;&lt;a class=&quot;markdownIt-Anchor&quot; href=&quot;#final-effect&quot;&gt;&lt;/a&gt; Final effect&lt;/h1&gt;
&lt;p&gt;The main functions are as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The node is divided into two parts, the top half is the icon and the bottom half is the text
&lt;ul&gt;
&lt;li&gt;When the mouse is placed on the icon, it will produce a diffusion effect of water ripples, and a circle of borders will appear at the same time&lt;/li&gt;
&lt;li&gt;Text needs to be underlined and have a white background, and the water ripple effect cannot be blocked by the white background&lt;/li&gt;
&lt;li&gt;The underline of the text needs to be a square&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The connection should have a gradual change of color, and the gradual change of color should be from the beginning of the arrow to the end of the arrow, and if the two-way relationship is supported, how to achieve two edges&lt;/li&gt;
&lt;li&gt;There should be a Label in the middle of the connection&lt;/li&gt;
&lt;li&gt;Nodes and connections should support translucency&lt;/li&gt;
&lt;li&gt;The overall layout should be a force-oriented layout, and node dragging is supported. When dragging, nodes cannot overlap, but other nodes cannot be dragged due to connection (this point is raised separately because G6’s built-in force-oriented layout nodes will be dragged).&lt;/li&gt;
&lt;/ul&gt;</summary>
    
    
    
    <category term="Sundry" scheme="https://sunra.top/en/categories/Sundry/"/>
    
    
  </entry>
  
  <entry>
    <title>Management Methodology of Technical Personnel (1) - Basic Framework of Management</title>
    <link href="https://sunra.top/en/posts/44656/"/>
    <id>https://sunra.top/en/posts/44656/</id>
    <published>2023-03-05T02:59:20.000Z</published>
    <updated>2026-06-13T06:03:37.130Z</updated>
    
    <content type="html"><![CDATA[<p>As a programmer, we usually focus on management knowledge, initially may be Design pattern, management is the complexity of a certain requirement, slowly, we will begin to pay attention to domain division, DDD, business modeling, etc., these management is the complexity of the system, and then later, the complexity of things gradually evolved to our personal can not handle, we need teamwork, here is the management of project complexity.</p><p>In fact, these three will exist and are interrelated from beginning to end, and many concepts are similar, but we need to gradually participate in the actual work to realize this complexity step by step.</p><p>Regarding Design pattern and domain-driven design, my previous blogs have summarized some of the books and specific practices I have read. This time, combined with my personal experience and the book “Knowledge and Action”, I will summarize some methodologies in project management…</p><span id="more"></span><p>Let’s talk about some of my biggest takeaways from the book:</p><ol><li>Role recognition is very important. If you don’t realize that you are already a manager, then you won’t recognize what managers should do. Instead, you will compete with team members, not doing what you should do, and letting others do it. Family has nothing to do.</li><li>The system is very important. Don’t shout slogans for culture, values, etc. If you want team members to do something, you must let the system reward this behavior. If you don’t want team members to do something, you must let the system punish this behavior.</li><li>Identifying the work content of team members is what managers should do. If you don’t know what your members are doing, don’t be a manager. It means that you haven’t recognized yourself as a manager.</li><li>Material rewards may not be effective beyond a certain level, but if the material rewards are not in place, the lethality is the greatest.</li><li>The implementation of any system has a cost, such as time cost, Opportunity Cost, do not copy all systems</li><li>For knowledge-creating teams, the lower limit is guaranteed by processes or automation tools, and the upper limit depends on people. Many teams are reversed, and people are guaranteed the lower limit by punishing people by the system. It is necessary to hand over repetitive work to automated processes and free people to do creative work.</li><li>There is no good or bad management tools. Your team needs to execute efficiently and does not need to create much. Then KPI. If you need to create a line, then OKR. Note that what is said here is the spirit of the two tools. There are also many people who use OKR as KPI. tuan</li><li>Team culture is very important, but it is also important whether the team culture you imagine is the same as what you have shaped. At the same time, it is also necessary to recognize that the quality of different aspects of people is Normal Distribution. Don’t expect people under your command to be inherently efficient and collaborative, what’s the use of managers.</li></ol><h2 id="manage-the-hesitation-of-the-intersection"><a class="markdownIt-Anchor" href="#manage-the-hesitation-of-the-intersection"></a> Manage the hesitation of the intersection</h2><h3 id="what-are-the-development-paths-for-engineers"><a class="markdownIt-Anchor" href="#what-are-the-development-paths-for-engineers"></a> What are the development paths for engineers?</h3><ul><li><p>Technical category</p><ul><li>Architect</li><li>Technical experts</li></ul></li><li><p>Management category</p><ul><li>Technical Manager</li><li>Professional manager</li></ul></li><li><p>Entrepreneurship</p><ul><li>Founder</li><li>Technical partner</li></ul></li><li><p>Consultants</p><ul><li>Investment advisor</li><li>Management consultants</li></ul></li></ul><h3 id="who-is-likely-to-enter-management-positions"><a class="markdownIt-Anchor" href="#who-is-likely-to-enter-management-positions"></a> Who is likely to enter management positions?</h3><ul><li><p>Time of day</p><p>It is best to go to those fast-growing industries and companies. In a stable industry, it takes a long wait to get into a management position. But it is not to go to start-up companies and small companies. Tianshi round and A round companies are mostly in their survival period and have not yet scaled up, and companies without scale do not need you to manage them. This kind of start-up company is more suitable for the direction of technical partners rather than technical managers. Don’t always change companies, because it is not good for improving management ability, because most of the time you are doing the same level of repetition.</p></li><li><p>Geographical location</p><p>It is their own strengths, abilities and the work content they are responsible for<br />The first category is the module responsible for the overall situation, and the core is “wide”.<br />The second category is responsible for the core technical modules, the core is “deep”</p></li><li><p>People and</p><p>The key to people is whether they can get the support of others</p><ol><li>Opportunities. Platform and resource support, generally superior</li><li>Companionship and support for common growth. Generally, it is a peer manager</li><li>Guidance and direction of progress. Generally a mentor, mentor, management coach or superior</li><li>Emotional support. Empower you to face difficulties and setbacks</li></ol></li></ul><h3 id="torn-do-you-want-to-switch-back-to-technology"><a class="markdownIt-Anchor" href="#torn-do-you-want-to-switch-back-to-technology"></a> Torn: Do you want to switch back to technology?</h3><ul><li><p>Fear of losing technical ability</p><ul><li>Establish a learning mechanism</li><li>Ask an expert</li><li>Co-creation</li></ul></li><li><p>Worried about not being able to manage it well</p><p>Management and technology are not completely unrelated</p><ul><li>Recognize the reality, when the business complexity to a certain extent, it is not with personal technology can be solved, project management is imperative</li></ul></li></ul><h3 id="how-to-stay-technologically-competitive"><a class="markdownIt-Anchor" href="#how-to-stay-technologically-competitive"></a> How to Stay Technologically Competitive</h3><p>From Technology Implementer to Technology Applier, your relationship with technology changes, and the meaning of the word technical capability changes</p><p>What Has Changed From Technology Implementer to Technology Applier?</p><ul><li><p>For Technology Implementers, programming capabilities, coding capabilities, technical skills and technical evaluation capabilities are all required, and the main concern is how to get things done</p></li><li><p>For technology users, the ability to evaluate technology has become particularly important. The main concern of technical managers is whether to do it and what it is, and it is necessary to make decisions and judgments after comprehensive evaluation</p><ul><li>manager’s skills are not reflected in the technical expertise and coding proficiency, but in the technical evaluation ability</li><li>More and more people with stronger professional skills in the team are inevitable and a good phenomenon</li><li>Managers want to convince employees, and more importantly, lead employees to achieve good performance, get good returns, and help employees grow better</li></ul></li><li><p>Latitude of technical evaluation</p><ul><li><p>Evaluation of results</p><ul><li>What’s this about?</li><li>What do you want?</li><li>From several latitudes to measure the results, from which technical indicators to accept the results (to start with the end, the results can be measured)</li></ul></li><li><p>Feasibility assessment</p><ul><li><p>can you do it</p></li><li><p>Is it worth it?</p><ul><li><p>Cost</p><ul><li><p>Cost of resources invested: in people and property</p></li><li><p>Cost of technical maintenance</p><ul><li>Technical selection costs</li><li>Technology upgrade costs</li><li>Troubleshooting costs</li><li>Code maintenance costs</li></ul></li><li><p>Opportunity Cost</p></li><li><p>Collaboration costs</p></li></ul></li><li><p>Gains</p></li></ul></li></ul></li><li><p>threat and risk assessment</p><ul><li>Those technical risks need to be prepared for a rainy day</li><li>The possibility and boundary of the maximum loss caused by the technical solution</li></ul></li></ul></li><li><p>Sources of technical judgment</p><ul><li><p>The new manager’s technical judgment comes mostly from previous experience</p></li><li><p>Ways to improve technical judgment</p><ul><li>Establish a learning mechanism</li><li>special project technical research project</li><li>Exchange with technical experts</li><li>Listen to work reports</li></ul></li></ul></li></ul><h3 id="management-style"><a class="markdownIt-Anchor" href="#management-style"></a> Management style</h3><p>The so-called management style is essentially the way you collaborate with the team, that is, your relative relationship with the team, that is, where you are on the team</p><ul><li><p>Give orders</p><p>Command-based management. When there is no room for error in a job, and you are the only person who knows and has the most control, an command-based you is better able to reduce risks and achieve goals. Therefore, command management is more suitable for scenarios that require mandatory</p><ul><li>Command the whole process, but not personally</li><li>Don’t focus on people, keep your eyes on goals and results, and pay less attention to people’s development and growth</li><li>Strong execution, but difficult to develop team layer</li></ul></li><li><p>Lead by example</p><p>Supportive management. When a team needs cohesion and fighting spirit to work hard, a supportive you will contribute to good results. Therefore, supportive management can especially promote team morale and cohesion, and has an advantage in increasing everyone’s enthusiasm and enthusiasm</p><ul><li>Be at the forefront of everything and blend in with the team</li><li>Emphasis on people is not important, will not neglect to do things, but more concerned about people’s feelings, the way to support employees tend to do things directly for employees, rather than instructing employees to do things independently<br />Employees have a sense of belonging, but can’t manage large teams</li></ul></li><li><p>Inspiring coaching type</p><p>When there are some core talents that need to be trained and team development needs echelons, a coaching you will bring obvious results. Not only can things be done well, but team members can also grow rapidly. Although the execution speed is usually not fast, it will not deviate from the direction</p><ul><li>Will not personally help employees do things, but will coach and inspire employees how to get the job done, and provide encouragement, support and feedback</li><li>Not only care about whether employees have been exercised and grown in the process of doing things, but also care about whether the things themselves are well completed</li><li>Helps to build a team layer, but this method consumes a lot of energy for managers, and it is difficult to cover all members, which is suitable for the training of the core team</li></ul></li><li><p>The inaction type</p><p>When the team layer is mature and team members need to play space, an empowered you can provide the most appropriate management method. Because what mature subordinates need most is not your help, but your decentralization.</p><ul><li>After arranging the work, let it go and fully delegate the work to the team members</li><li>For immature teams, members will grow wildly, and for mature teams, members will have a good space to play</li></ul></li></ul><h3 id="how-to-manage-self-confidence"><a class="markdownIt-Anchor" href="#how-to-manage-self-confidence"></a> How to Manage Self-Confidence</h3><ul><li><p>Source of lack of confidence</p><ul><li>Insufficient management experience and lack of management methods</li><li>Compare with team members</li><li>Carry a heavy psychological burden and worry about disappointing the expectations of superiors</li></ul></li><li><p>How to deal with it</p><ul><li><p>Capability three core</p><p>Understand what abilities you have and transfer them. Knowledge is not transferable, but skills and talents can. You can praise yourself through friends, “Gapro Strength Recognizer 2.0” or “VIA Character Strength” and other related theories and assessment tools</p><p>Knowledge: knowing and understanding content and information</p><ul><li><p>Skills: Operate and complete techniques</p><ul><li>Quick learning ability</li><li>Progress control capability</li></ul></li><li><p>Talent</p><ul><li>Confidence</li><li>Looking ahead</li></ul></li></ul></li><li><p>Don’t antagonize team members</p><p>Now as the leader of the team, you need to separate yourself from the comparison and competition with people and team members to see what kind of team you will bring out, and in the process, you can contribute to the company, team and team members. What kind of achievements and growth do you bring.<br />What you need to do is to use everyone’s strength to make better results, not just because of your position to convince everyone.</p></li></ul><p>Obtain continuous positive external feedback</p><ul><li><p>Establish positive feedback channels, especially communication with superiors. You can make an appointment with superiors for a routine communication mechanism, report team work regularly, and solicit superiors’ opinions and evaluations on some important work</p><ul><li>In your opinion, what one or two things do I do well?</li><li>Do you see any obvious improvement?</li><li>I want to know what you value more</li></ul></li></ul></li></ul><h2 id="framework-of-management"><a class="markdownIt-Anchor" href="#framework-of-management"></a> Framework of management</h2><h3 id="what-is-management"><a class="markdownIt-Anchor" href="#what-is-management"></a> What is management</h3><p>Management issues are not only complex but also unstable:</p><ol><li>In the industrial era, the pursuit of strict control, emphasis on external drive, and more reliance on the reward and punishment mechanism of carrots and sticks.</li><li>The era of knowledge economy pursues innovation, emphasizes internal drive, and relies more on stimulating employee autonomy.<br />Whether it is internal drive or external drive, both material and spiritual aspects are needed<br />If material rewards cannot guarantee the survival of employees, no matter how spiritual encouragement is ineffective.<br />The difference may only be that the profound encouragement of external drive is biased towards pua, the management tool is biased towards kpi, the profound encouragement of internal drive is biased towards trust, decentralization and other positive aspects, and the management tool is biased towards OKR (the most important thing about OKR is the spirit, which does not mean that the management method of OKR is OKR., there is no difference between OKR and kpi in many companies)</li></ol><ul><li><p>Development of management</p><ul><li><p>Classical management methodology</p><p>Management is a universal human activity composed of five elements: planning, organizing, directing, coordinating and controlling, emphasizing the process of management and the controllability of “doing things”</p></li><li><p>Frederick, father of scientific management</p><p>Management is knowing exactly what you want someone to do and making him do it in the best way possible. His focus is two:</p><p>1 What does one do?<br />2. How does one do it<br />Have obvious goals, directions and ways of doing things, emphasizing goals and doing things</p></li><li><p>Peter Drucker, the father of modern management</p><p>Management is a kind of practice. Its essence is not “knowledge”, but “action”. Its verification does not lie in logic, but in results. Its sole authority is “achievement”. His statement focuses on practicality and results, emphasizing “goals”.</p></li><li><p>Contemporary Management Master Stephen Robin</p><p>The so-called management refers to the process of working with or through others to make activities more effective. There are three elements hidden behind this: “people”, “process”, and “effectiveness.” In formal terms, it is called organization, process, and direction</p></li></ul></li><li><p>Management is roughly divided into three stages, corresponding to three different eras</p><p>Focus on the Process: Emphasize how things are done</p><p>Industrial production era: In the early industrial era, the business model with the typical characteristics of the assembly line, “standardization” and “doing things according to the rules” are the most important work values, and any employee’s initiative to innovate may cause great damage to the assembly line, so the focus of management is on the “process”, emphasizing doing things</p><ul><li><p>Focus on process and goals: emphasis on setting goals and achieving them by mastering how to “do things”</p><p>Industrial competition era: In the middle and late industrial era, as competition became more and more fierce, when production itself could not bring significant competitive advantages, managers began to consider how to make production more “effective”, that is, to produce more performance, so more and more Attention is paid to the purpose of production. In addition to continuing to emphasize “doing things”, management also emphasizes “doing things for what”, that is, “goals”</p></li><li><p>Focus on team, process, and goals: emphasis on setting “goals” and achieving them by mastering how to “lead people” and how to “do things”</p><p>The era of knowledge economy: After the industrial development is more fully developed, the trend of “keeping upright” is becoming more and more obvious, especially after the information industry has brought us to the era of knowledge economy, “creativity” has become the life infra of many enterprises. Obviously, among all the factors of production, only “people” are creative, so the status of “people” in management has been improved</p></li></ul></li></ul><h3 id="what-is-leadership"><a class="markdownIt-Anchor" href="#what-is-leadership"></a> What is leadership</h3><p>Leadership is the art of mobilizing people to work toward a shared vision.<br />This sentence includes “mobilize everyone”, “common vision”, and “work hard”, which correspond to “bring people”, “goal”, and “do things” in the third stage of management respectively.</p><ul><li>Bring someone</li><li>Target</li><li>do things</li></ul><h3 id="the-basic-framework-of-management-managing-sandwiches"><a class="markdownIt-Anchor" href="#the-basic-framework-of-management-managing-sandwiches"></a> The basic framework of management: managing sandwiches</h3><p>We take the ubiquitous air-like cognition as the “day” of management, the communication that carries all work as the “ground” of management, and put the daily needs of managers to see the direction, lead people, and do things in the middle to form a management framework. Managers are constantly working between the “heaven” of roles and the “earth” of communication - see direction, lead people, do things</p><ul><li><p>Role recognition</p><p>Once you jump on the carriage, you must first be a coachman, which is called “cognitive management”. Corresponding to management, when we become a team manager from an engineer, we also need to have a full understanding of the role of “manager”</p></li><li><p>Management planning: objectives</p><p>Before starting the carriage, you need to first see what the carriage is pulling, where the destination is, what is the situation of the horse team, and which path to choose. Corresponding to management, it is to figure out the basic functions of the team, what is the goal of the work, the status of the team and the path selection</p><ul><li><p>Meaning</p><p>Management planning is the vision of management constructed in the mind, which represents the direction of future management</p></li><li><p>Form</p><p>From the perspective of the situation, the management plan is an agreement that reflects the consensus reached between you and your superior regarding the future management work</p></li><li><p>Content</p><p>Management planning is to answer the question of what resources your team is going to devote to achieve what goals next</p></li><li><p>Appear scene</p><ol><li>Quarterly or annual alternation, you need to re-examine the team’s input and output.</li><li>When the team or the business scope is significantly changed due to organizational adjustment</li><li>When parachuting into a new team to manage</li></ol></li><li><p>Management Planning Four-factor Verification</p><p>The three elements of goal, team and path are related to each other, and they are all planned and designed based on function. Function is the starting point and core of planning</p><ul><li><p>Functions: what is this car and what does it do</p><p>Corresponding function, what does your team do?<br />Figure out what responsibilities and missions your team undertakes, decide what kind of work goals need to be set, and what latitudes to use to measure goals; determine what kind of people need to join the team and how many people are needed; decide what kind of choices Means, and what resources to invest to get the job done.</p><p>The important thing here is to start with the end in mind.</p></li><li><p>Target: Where is this car going?</p><p>Goal, what do you want to produce?</p><p>Having clarity on where to go allows you to assess what kind of horses are needed, how many are needed, and what routes are available.</p><p>The question of where to go is the second element of management planning, called goals. Few people question why goals are set, because everyone takes them for granted and its necessity is self-evident. But for technical teams, setting clear and specific goals is difficult.</p></li><li><p>Team: What is the current status of the horse team?</p><p>Team, who do you rely on?</p><p>When taking over a new type of team, you should also take stock of what team you are leading, because all the work is done by the team, and the team is the real driver. So, take stock of your team, and see how to upgrade and improve your team in the “rush process”, and consider what kind of team you expect to gain after achieving your goals</p></li><li><p>Path: Which way to drive the carriage</p><p>Path, what are you going to invest in?</p><p>Different path choices will bring about differences in input resources. Corresponding to management, you need to choose the ways and means to achieve your goals, and apply to the company for resources of the corresponding category and scale accordingly. Since the company’s budget is to be done in advance, it should be considered in management planning.</p><p>Breaking down the goal into paths is for resource budgeting<br />The goal is dismantled as a plan, and the purpose is to implement it.</p></li></ul></li></ul></li><li><p>Team building: bring people</p><p>After the direction is clear, start driving the carriage forward. In this process, you need to continue to do two things, grab the reins of the horse, coordinate the entire horse team, and let the horses work together. Corresponding to management, it is team building and leading people.</p><ul><li><p>Three levels</p><ul><li><p>Individual: able to run</p><ul><li>Individual ability: employee ability development</li><li>Willingness: Employee Motivation</li></ul></li><li><p>Between individuals: run fast</p><ul><li><p>work allocation</p><ul><li><p>The goal is the same</p></li><li><p>Same standard</p><p>Don’t chase quality alone, chase progress alone</p></li></ul></li><li><p>Collaboration level</p><p>Is there good trust and tacit understanding among team members, and is collaboration efficient and smooth?</p></li></ul></li><li><p>Overall: Run away</p><ul><li><p>Echelon</p><p>The ability composition of the old and new team members. If a team is only supported by one or two experts, then the team is very fragile. This belongs to the “hardware” of the team as a whole.</p></li><li><p>Culture</p><p>The culture and values of the team can also be called the team atmosphere. Team members can find a very strong sense of identity here, and everyone is very clear about what is important and what is not important in this team, what should be and what should not be.</p><p>Team culture is not shouting slogans, but through the system to ensure that what you want team members to do, you have to reward through the system, you need team members do not do anything, through the system to punish</p></li></ul></li></ul></li></ul></li><li><p>Task management: doing things</p><p>While waving the whip, he commanded the horse team to reach milestone after milestone., is to complete one task after another, corresponding to management, is to complete one task after another</p><ul><li>beforehand: what to do, prioritize</li><li>In progress: Execute landing</li><li>After the fact: how to do it better. Autonomous driving, process mechanism</li></ul></li><li><p>Communication feedback</p><p>In the process of driving the carriage, the coachman kept shouting or waving the whip, which was to communicate with the horse team and the surrounding environment.</p><ul><li><p>Scene</p><ul><li>Upward communication</li><li>Communicate down</li><li>Horizontal communication</li></ul></li><li><p>Purpose</p><ul><li>Building relationships</li><li>Sync information</li><li>Expressing emotions</li><li>Persuasion influence</li></ul></li><li><p>Content</p><ul><li>Plan</li><li>Progress</li><li>Risk</li><li>Synergy</li><li>Personnel</li></ul></li><li><p>Way</p><ul><li>In person</li><li>Phone</li><li>Message</li><li>E-mail</li><li>Collaboration Platform</li></ul></li><li><p>Tools</p><ul><li>3F Listening</li><li>Proactive feedback</li><li>Playback confirmed</li></ul></li><li><p>Consciousness</p><ul><li>Proactive notification</li><li>Empathy</li><li>Closed loop consciousness</li><li>Conclusion first</li></ul></li></ul></li></ul>]]></content>
    
    
    <summary type="html">&lt;p&gt;As a programmer, we usually focus on management knowledge, initially may be Design pattern, management is the complexity of a certain requirement, slowly, we will begin to pay attention to domain division, DDD, business modeling, etc., these management is the complexity of the system, and then later, the complexity of things gradually evolved to our personal can not handle, we need teamwork, here is the management of project complexity.&lt;/p&gt;
&lt;p&gt;In fact, these three will exist and are interrelated from beginning to end, and many concepts are similar, but we need to gradually participate in the actual work to realize this complexity step by step.&lt;/p&gt;
&lt;p&gt;Regarding Design pattern and domain-driven design, my previous blogs have summarized some of the books and specific practices I have read. This time, combined with my personal experience and the book “Knowledge and Action”, I will summarize some methodologies in project management…&lt;/p&gt;</summary>
    
    
    
    <category term="Sundry" scheme="https://sunra.top/en/categories/Sundry/"/>
    
    
  </entry>
  
  <entry>
    <title>Force-oriented algorithm</title>
    <link href="https://sunra.top/en/posts/62967/"/>
    <id>https://sunra.top/en/posts/62967/</id>
    <published>2023-02-23T02:59:53.000Z</published>
    <updated>2026-06-13T06:03:37.122Z</updated>
    
    <content type="html"><![CDATA[<p>Recently, I need to implement a relational graph in my work. The node layout in the graph needs to use force-oriented layout, so I was interested in the force-oriented algorithm involved, and I went to study it.</p><p>Force-directed graph drawings can be used to describe the relationships between nodes of a graph, distributing nodes to reasonable positions on the canvas, such as describing relationships between enterprises, interpersonal relationships in social networks, etc.</p><span id="more"></span><h1 id="basic-principle-of-algorithm"><a class="markdownIt-Anchor" href="#basic-principle-of-algorithm"></a> Basic principle of algorithm</h1><p>Let’s first take a look at a rendering:</p><p><img src="https://res.cloudinary.com/dvtfhjxi4/image/upload/v1677373207/origin-of-ray/bVbgUak_jbxebp.png" alt="" /></p><p>The distribution of the points in the above figure is calculated by the force guidance algorithm, which is to regard the nodes as the same charge, and there is a repulsive force between them. This repulsive force simulates Coulomb’s law, and the closer the repulsive force, the greater the repulsive force; if there is a connection between two points, it is regarded as an attractive force between the two points. This attractive force simulates Hooke’s law, and the farther away the attractive force is, the greater the attractive force.</p><p>In the initial state, we randomly place points, and then these points will move in space due to attractive forces and repulsive forces until a balance is reached, forming a force-oriented layout.</p><h2 id="repulsive-force"><a class="markdownIt-Anchor" href="#repulsive-force"></a> Repulsive force</h2><p>Consider each node as an electric charge, and there is a repulsive force between the charges, which is the Coulomb force. According to Coulomb’s law, the repulsive force between electrons can be calculated as follows:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>F</mi><mo>=</mo><msub><mi>k</mi><mi>e</mi></msub><mfrac><mrow><msub><mi>q</mi><mn>1</mn></msub><msub><mi>q</mi><mn>2</mn></msub></mrow><msup><mi>r</mi><mn>2</mn></msup></mfrac><mover accent="true"><mi>e</mi><mo stretchy="true">→</mo></mover></mrow><annotation encoding="application/x-tex">F = k_e\frac{q_1q_2}{r^2}\overrightarrow{e}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.7935599999999998em;vertical-align:-0.686em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.03148em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.1075599999999999em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.740108em;"><span style="top:-2.9890000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.03588em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9525600000000001em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">e</span></span></span><span class="svg-align" style="top:-3.43056em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail" style="height:0.522em;min-width:0.888em;"><svg width='400em' height='0.522em' viewBox='0 0 400000 522' preserveAspectRatio='xMaxYMin slice'><path d='M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67 151.7 139 205zm0 0v40h399900v-40z'/></svg></span></span></span></span></span></span></span></span></span></span></p><p>We can assume that $q_1 and q_2 $are both 1, then the above formula becomes</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>F</mi><mo>=</mo><msub><mi>k</mi><mi>e</mi></msub><mfrac><mn>1</mn><msup><mi>r</mi><mn>2</mn></msup></mfrac><mover accent="true"><mi>e</mi><mo stretchy="true">→</mo></mover></mrow><annotation encoding="application/x-tex">F = k_e\frac{1}{r^2}\overrightarrow{e}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:2.00744em;vertical-align:-0.686em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.03148em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">e</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.32144em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">r</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.740108em;"><span style="top:-2.9890000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord accent"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9525600000000001em;"><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">e</span></span></span><span class="svg-align" style="top:-3.43056em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail" style="height:0.522em;min-width:0.888em;"><svg width='400em' height='0.522em' viewBox='0 0 400000 522' preserveAspectRatio='xMaxYMin slice'><path d='M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67 151.7 139 205zm0 0v40h399900v-40z'/></svg></span></span></span></span></span></span></span></span></span></span></p><h2 id="attractive-force"><a class="markdownIt-Anchor" href="#attractive-force"></a> Attractive force</h2><p>Some particles are entangled by some edges that produce a spring-like Hooker attractive force:</p><p class='katex-block'><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><msub><mi>F</mi><mi>s</mi></msub><mo>=</mo><msub><mi>k</mi><mi>s</mi></msub><mo stretchy="false">(</mo><mi>x</mi><mo>−</mo><msub><mi>x</mi><mn>0</mn></msub><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">F_s = k_s(x - x_0)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">F</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.13889em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">s</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:-0.03148em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">s</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span></span></p><p>The repulsive and attractive forces continue to act, the particles tend to balance after continuous displacement, and gradually no longer have relative displacement, and the energy is continuously consumed, and finally tends to zero.</p><p>Under the action of attractive force and repulsive force, the coordinates are constantly updated, and after multiple iterations, a stable state is reached, and the convergence is over. Parameters and iterations need to be debugged.</p><h2 id="calculation-step"><a class="markdownIt-Anchor" href="#calculation-step"></a> Calculation step</h2><p>If we want to use code to implement the simplified layout of the force guide diagram, we need several steps.</p><ul><li>Set point data nodes, link data links.</li><li>Random positioning of points.</li><li>Render View</li><li>Execution algorithm calculates position, renders view (repeated N times)</li></ul><h1 id="code-implementation"><a class="markdownIt-Anchor" href="#code-implementation"></a> Code implementation</h1><p>In fact, understand the above process, you can fully implement a version of the force-oriented algorithm, I just provide a simple version here, each person to achieve the algorithm and the final effect may be completely different</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Node</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">x</span> = <span class="literal">null</span>;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">y</span> = <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Edge</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">source, target</span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">source</span> = source;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">target</span> = target;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">CANVAS_WIDTH</span> = <span class="number">1000</span>;</span><br><span class="line"><span class="keyword">const</span> <span class="variable constant_">CANVAS_HEIGHT</span> = <span class="number">1000</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">ForceDirected</span> &#123;</span><br><span class="line">  <span class="title function_">constructor</span>(<span class="params">n</span>) &#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">mNodeList</span> = <span class="keyword">new</span> <span class="title class_">Array</span>(n).<span class="title function_">fill</span>(<span class="number">0</span>).<span class="title function_">map</span>(<span class="keyword">new</span> <span class="title class_">Node</span>());</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">mEdgeList</span> = []</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">mDxMap</span> = [];</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">mDyMap</span> = [];</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">ejectFactor</span> = <span class="number">6</span>;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">condenseFactor</span> = <span class="number">3</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; n; i++) &#123;</span><br><span class="line">      <span class="keyword">const</span> edgeCount = <span class="title class_">Math</span>.<span class="title function_">random</span>() * <span class="number">8</span> + <span class="number">1</span>;</span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">let</span> j = <span class="number">0</span>; j &lt; edgeCount; j++) &#123;</span><br><span class="line">        <span class="keyword">let</span> targetId = <span class="title class_">Math</span>.<span class="title function_">floor</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * n);</span><br><span class="line">        <span class="keyword">let</span> edge = <span class="keyword">new</span> <span class="title class_">Edge</span>(i, targetId);</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">mEdgeList</span>.<span class="title function_">push</span>(edge);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">coefficient</span> = <span class="title class_">Math</span>.<span class="title function_">sqrt</span>(<span class="variable constant_">CANVAS_WIDTH</span> * <span class="variable constant_">CANVAS_HEIGHT</span> / mNodeList.<span class="property">length</span>);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> initialSize = <span class="number">40.0</span>;</span><br><span class="line">    <span class="keyword">const</span> initialX = <span class="variable constant_">CANVAS_WIDTH</span> * <span class="number">.5</span>;</span><br><span class="line">    <span class="keyword">const</span> initialY = <span class="variable constant_">CANVAS_HEIGHT</span> * <span class="number">.5</span>;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i <span class="keyword">in</span> <span class="variable language_">this</span>.<span class="property">mNodeList</span>) &#123;</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">mNodeList</span>[i].<span class="property">x</span> = initialX + initialSize * (<span class="title class_">Math</span>.<span class="title function_">random</span>() - <span class="number">.5</span>);</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">mNodeList</span>[i].<span class="property">y</span> = initialY + initialSize * (<span class="title class_">Math</span>.<span class="title function_">random</span>() - <span class="number">.5</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">//Calculate repulsion</span></span><br><span class="line">  <span class="title function_">calculateRepulsive</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> distX, distY, dist;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="variable language_">this</span>.<span class="property">mNodeList</span>.<span class="property">length</span>; i++) &#123;</span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">let</span> j = <span class="number">0</span>; j &lt; <span class="variable language_">this</span>.<span class="property">mNodeList</span>.<span class="property">length</span>; j++) &#123;</span><br><span class="line">        distX = <span class="variable language_">this</span>.<span class="property">mNodeList</span>[i].<span class="property">x</span> - <span class="variable language_">this</span>.<span class="property">mNodeList</span>[j].<span class="property">x</span>;</span><br><span class="line">        distY = <span class="variable language_">this</span>.<span class="property">mNodeList</span>[i].<span class="property">y</span> - <span class="variable language_">this</span>.<span class="property">mNodeList</span>[j].<span class="property">y</span>;</span><br><span class="line">        dist = <span class="title class_">Math</span>.<span class="title function_">sqrt</span>(distX * distX + distY * distY);</span><br><span class="line">        <span class="keyword">if</span> (dist &gt; <span class="number">0</span> &amp;&amp; dist &lt; <span class="number">250</span>) &#123;</span><br><span class="line">          <span class="variable language_">this</span>.<span class="property">mDxMap</span>[i] = distX * <span class="variable language_">this</span>.<span class="property">ejectFactor</span> / <span class="title class_">Math</span>.<span class="title function_">pow</span>(dist, <span class="number">2</span>);</span><br><span class="line">          <span class="variable language_">this</span>.<span class="property">mDyMap</span>[i] = distY * <span class="variable language_">this</span>.<span class="property">ejectFactor</span> / <span class="title class_">Math</span>.<span class="title function_">pow</span>(dist, <span class="number">2</span>);</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="title class_">Calculate</span> the attractive force</span><br><span class="line">  <span class="title function_">calculateTraction</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> startNode, endNode;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> e = <span class="number">0</span>; e &lt; mEdgeList.<span class="property">length</span>; e++) &#123;</span><br><span class="line">      <span class="keyword">const</span> eStartID = mEdgeList[e].<span class="property">source</span>;</span><br><span class="line">      <span class="keyword">const</span> eEndID = mEdgeList[e].<span class="property">target</span>;</span><br><span class="line">      startNode = <span class="variable language_">this</span>.<span class="property">mNodeList</span>[eStartID];</span><br><span class="line">      endNode = <span class="variable language_">this</span>.<span class="property">mNodeList</span>[eEndID];</span><br><span class="line">      <span class="keyword">let</span> distX, distY, dist;</span><br><span class="line">      distX = startNode.<span class="property">x</span> - endNode.<span class="property">x</span>;</span><br><span class="line">      distY = startNode.<span class="property">y</span> - endNode.<span class="property">y</span>;</span><br><span class="line">      dist = <span class="title class_">Math</span>.<span class="title function_">sqrt</span>(distX * distX + distY * distY);</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">mDxMap</span>[eStartID] = <span class="variable language_">this</span>.<span class="property">mDxMap</span>[eStartID] - distX * dist / k * <span class="variable language_">this</span>.<span class="property">condenseFactor</span>;</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">mDyMap</span>[eStartID] = <span class="variable language_">this</span>.<span class="property">mDyMap</span>[eStartID] - distY * dist / k * <span class="variable language_">this</span>.<span class="property">condenseFactor</span>;</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">mDxMap</span>[eEndID] = <span class="variable language_">this</span>.<span class="property">mDxMap</span>[eEndID] + distX * dist / k * <span class="variable language_">this</span>.<span class="property">condenseFactor</span>;</span><br><span class="line">      <span class="variable language_">this</span>.<span class="property">mDyMap</span>[eEndID] = <span class="variable language_">this</span>.<span class="property">mDyMap</span>[eEndID] + distY * dist / k * <span class="variable language_">this</span>.<span class="property">condenseFactor</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="title function_">updateCoordinates</span>(<span class="params"></span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> maxt = <span class="number">4</span>, maxty = <span class="number">3</span>; <span class="comment">//Additional coefficients.</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> v = <span class="number">0</span>; v &lt; mNodeList.<span class="property">length</span>; v++) &#123;</span><br><span class="line">      <span class="keyword">let</span> node = mNodeList[v];</span><br><span class="line">      <span class="keyword">let</span> dx = <span class="title class_">Math</span>.<span class="title function_">floor</span>(mDxMap[v]);</span><br><span class="line">      <span class="keyword">let</span> dy = <span class="title class_">Math</span>.<span class="title function_">floor</span>(mDyMap[v]);</span><br><span class="line">  </span><br><span class="line">      <span class="keyword">if</span> (dx &lt; -maxt) dx = -maxt;</span><br><span class="line">      <span class="keyword">if</span> (dx &gt; maxt) dx = maxt;</span><br><span class="line">      <span class="keyword">if</span> (dy &lt; -maxty) dy = -maxty;</span><br><span class="line">      <span class="keyword">if</span> (dy &gt; maxty) dy = maxty;</span><br><span class="line">      node.<span class="property">x</span> = node.<span class="property">x</span> + dx &gt;= <span class="variable constant_">CANVAS_WIDTH</span> || node.<span class="property">x</span> + dx &lt;= <span class="number">0</span> ? node.<span class="property">x</span> - dx : node.<span class="property">x</span> + dx;</span><br><span class="line">      node.<span class="property">y</span> = node.<span class="property">y</span> + dy &gt;= <span class="variable constant_">CANVAS_HEIGHT</span> || node.<span class="property">y</span> + dy &lt;= <span class="number">0</span> ? node.<span class="property">y</span> - dy : node.<span class="property">y</span> + dy;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="title function_">update</span>(<span class="params">iterateCount</span>) &#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; iterateCount; i++) &#123;</span><br><span class="line">      <span class="title function_">calculateRepulsive</span>();</span><br><span class="line">      <span class="title function_">calculateTraction</span>();</span><br><span class="line">      <span class="title function_">updateCoordinates</span>();</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    
    <summary type="html">&lt;p&gt;Recently, I need to implement a relational graph in my work. The node layout in the graph needs to use force-oriented layout, so I was interested in the force-oriented algorithm involved, and I went to study it.&lt;/p&gt;
&lt;p&gt;Force-directed graph drawings can be used to describe the relationships between nodes of a graph, distributing nodes to reasonable positions on the canvas, such as describing relationships between enterprises, interpersonal relationships in social networks, etc.&lt;/p&gt;</summary>
    
    
    
    <category term="Algorithm" scheme="https://sunra.top/en/categories/Algorithm/"/>
    
    
  </entry>
  
</feed>
