<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://blog.archifrog.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.archifrog.com/" rel="alternate" type="text/html" /><updated>2026-03-25T10:23:21+00:00</updated><id>https://blog.archifrog.com/feed.xml</id><title type="html">HU Qian</title><subtitle>HU Qian&apos;s Academic Blog!</subtitle><author><name>HU Qian</name><email>huqian.archi@outlook.com</email></author><entry><title type="html">English Title</title><link href="https://blog.archifrog.com/2026-01-16/sample" rel="alternate" type="text/html" title="English Title" /><published>2026-01-16T00:00:00+00:00</published><updated>2026-01-16T00:00:00+00:00</updated><id>https://blog.archifrog.com/2026-01-16/sample</id><content type="html" xml:base="https://blog.archifrog.com/2026-01-16/sample"><![CDATA[<hr />

<h2 id="lalala">lalala</h2>

<ul>
  <li>jkl</li>
  <li>sdkl</li>
  <li>
    <h2 id="数学公式示例">数学公式示例</h2>
  </li>
</ul>

<h3 id="行内公式">行内公式</h3>
<p>能量方程 $E = mc^2$ 是相对论的基础。</p>

<h3 id="行间公式">行间公式</h3>
<p>\(\int_a^b f(x)dx = F(b) - F(a)\)</p>

<h3 id="矩阵">矩阵</h3>
<p>\(\begin{bmatrix}
1 &amp; 2 &amp; 3 \\
4 &amp; 5 &amp; 6 \\
7 &amp; 8 &amp; 9
\end{bmatrix}\)</p>

<h3 id="多行公式">多行公式</h3>
<p>\(\begin{aligned}
\nabla \cdot \mathbf{E} &amp;= \frac{\rho}{\epsilon_0} \\
\nabla \cdot \mathbf{B} &amp;= 0
\end{aligned}\)</p>]]></content><author><name>HU Qian</name><email>huqian.archi@outlook.com</email></author><category term="默认分组" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Computational Toolkit for Architects</title><link href="https://blog.archifrog.com/2025-07-07/archi-geo" rel="alternate" type="text/html" title="Computational Toolkit for Architects" /><published>2025-07-07T00:00:00+00:00</published><updated>2025-07-07T00:00:00+00:00</updated><id>https://blog.archifrog.com/2025-07-07/archi-geo</id><content type="html" xml:base="https://blog.archifrog.com/2025-07-07/archi-geo"><![CDATA[<!-- Research Assignment -->

<div class="link-inline">
    <a class="in-text-icon" href="https://pypi.org/project/archigeo/" target="_blank">
        <i class="fa-solid fa-paperclip fa-fw"></i>
        PyPI
    </a>
</div>
<div class="link-inline">
    <a class="in-text-icon" href="" target="_blank">
        <i class="fa-solid fa-paperclip fa-fw"></i>
        Nuget
    </a>
</div>

<hr />

<p class="plainpassage-brief">
本文将介绍我开发的计算几何工具箱<strong>ArchiGeo</strong>。ArchiGeo系列工具包主要包含几何类库、优化计算、快速可视化等功能，旨在为建筑设计提供便携、集成、易用的运算功能。目前，工具包主要支持Python和C#调用。
</p>

<h5 class="chapter-heading-left">Python | archigeo</h5>

<p>Python版本的库名为archigeo。archigeo充分利用了python的简洁语法，将点线面等基础数据结构和python原有数据结构等价对应，同时提供常用的几何运算函数(geomutils)和几何类库(geomoop)，并将一些常用外部库做了再封装，从而实现一组统一API调用多种类库功能的丝滑体验。</p>

<pre><code class="language-txt">archigeo/
├── basic/
│   ├── numeric.pyd
│   ├── geomutils.pyd
│   ├── geomoop.pyd
├── compa/
│   ├── fieldgen.pyd
│   ├── ...
├── visual/
│   ├── pygame_extend.pyd
│   ├── ...
├── rhino/
│   ├── rhino_extend.pyd
</code></pre>

<p>工具库archigeo已经在多个项目中得到了充分应用，包括：</p>
<ul>
<li><a class="plainpassage-boldlink" href="/Research/AlphaPlot/">AlphaPlot</a> 应用亮点是平滑向量场中的弹簧系统对建筑走道的组合变化的模拟 </li>
<li><a class="plainpassage-boldlink" href="/Research/QuadraBlock/">QuadraBlock</a> </li>
<li><a class="plainpassage-boldlink" href="/Research/StandRecons/">StandRecons</a> 应用亮点是SmoothArcSerires类的设计和应用 </li>
<li><a class="plainpassage-boldlink" href="/Research/OvalAgent/">OvalAgent-PCM</a> 体育建筑智能设计助手的智能配参功能，亮点是看台碗碗边变换参数计算等</li>
</ul>

<p>目前archigeo已经在PyPI发布了试用版本，仅支持windows系统的python3.9和python3.12。开发工作还在进展中，未来将完善说明文档和发布开源版本。</p>

<h5 class="chapter-heading-left">.NET | ArchiGeoSharp</h5>

<p>C#版本的库名为ArchiGeoSharp。ArchiGeoSharp充分利用dotnet的内置语法功能，将几何对象的定义和运算以简洁的形式呈现。</p>

<pre><code class="language-txt">namespaces
├── ArchiGeo.Basic 无外部依赖的基础库
│   ├── ArchiGeo.Basic.Numeric 数值计算
│   ├── ArchiGeo.Basic.Geometry 二三维几何定义和运算
│   ├── ArchiGeo.Basic.Transform 坐标变换、关联判断、布尔运算等
├── ArchiGeo.Depute 常用库的托管和再封装
├── ArchiGeo.Raylex 快速可视化工具
├── ArchiGeo.GRBSolver 常用优化问题求解，依赖于授权的Gurobi软件
├── ArchiGeo.Rhinex 对接Rhino建模，依赖于授权的Rhino软件
</code></pre>

<p>工具库ArchiGeoSharp已经在多个项目中得到了充分应用，包括：</p>
<ul>
<li><a class="plainpassage-boldlink" href="/Research/ProtoMass/">ProtoMass</a> 应用亮点是RectAgent类在磁场力作用下的运动对建筑体块组合的模拟</li>
<li><a class="plainpassage-boldlink" href="/Research/OvalAgent/">OvalAgent-MSAcc</a> 体育建筑智能设计助手的加速版本</li>
</ul>

<p>目前开发工作还在进展中，未来将完善说明文档和发布开源版本和Nuget源。</p>]]></content><author><name>HU Qian</name><email>huqian.archi@outlook.com</email></author><category term="技术分享" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Rhino Dev</title><link href="https://blog.archifrog.com/2025-05-05/rhino-dev" rel="alternate" type="text/html" title="Rhino Dev" /><published>2025-05-05T00:00:00+00:00</published><updated>2025-05-05T00:00:00+00:00</updated><id>https://blog.archifrog.com/2025-05-05/rhino-dev</id><content type="html" xml:base="https://blog.archifrog.com/2025-05-05/rhino-dev"><![CDATA[<hr />

<p class="plainpassage-brief">RhinoDeveloper官网有非常丰富的文档，用于指导开发者快速上手二次开发工作。本文是对其常见问题及底层逻辑的注解，有助于开发者更好地使用相关API。当前内容为零散笔记，尚未完成系统化整理，有待后续完善。现有内容主要包括: Common/OpenNurbs/Inside/Compute/Shim等常用技术。</p>

<p><code class="language-plaintext highlighter-rouge">编辑中...</code></p>

<h5 class="chapter-heading-left">RhinoCommon</h5>

<ul>
  <li><strong>RhinoCommon的特性</strong>
    <ul>
      <li>主要版本为.Net-RhinoCommon</li>
      <li>通常需要在Rhino环境下运行</li>
      <li>相比CGAL等通常的计算几何库，抽象程度较低，容易上手许多</li>
    </ul>
  </li>
  <li><strong>python-Rhino的特性</strong>
    <ul>
      <li>python-Rhino是和.Net-RhinoCommon基本同构的包装</li>
      <li>
        <p>需要使用非python常用类型(rhino3dm同理)</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">Rhino.Geometry</span> <span class="k">as</span> <span class="n">rg</span>
<span class="kn">from</span> <span class="nn">System.Collections.Generic</span> <span class="kn">import</span> <span class="n">List</span>
<span class="n">points</span> <span class="o">=</span> <span class="n">List</span><span class="p">[</span><span class="n">rg</span><span class="p">.</span><span class="n">Point3d</span><span class="p">]()</span>
<span class="n">points</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">rg</span><span class="p">.</span><span class="n">Point3d</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="n">points</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">rg</span><span class="p">.</span><span class="n">Point3d</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="n">points</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">rg</span><span class="p">.</span><span class="n">Point3d</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="k">return</span> <span class="n">rg</span><span class="p">.</span><span class="n">Curve</span><span class="p">.</span><span class="n">CreateControlPointCurve</span><span class="p">(</span><span class="n">points2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
  <li><strong>python-rhinoscriptsyntax的特性</strong>
    <ul>
      <li>rhinoscriptsyntax是和.Net-RhinoCommon不同构的包装</li>
      <li>采用RhinoScript风格，可以理解为命令集»RhinoScript»rhinoscriptsyntax；上次技术咨询会会原厂专家也说到这个事儿…</li>
      <li>(存疑,也许并不是…)由于rhinoscriptsyntax库内的命令和ActiveDoc是强绑定，在云端执行的时候如果没有相应的RhinoDoc，理论上在AddToDoc和redraw的时候就会报错</li>
    </ul>
  </li>
</ul>

<h5 class="chapter-heading-left">OpenNurbs</h5>

<ul>
  <li><strong>OpenNurbs的特性</strong>
    <ul>
      <li>开源，在常规环境下可以运行.</li>
      <li>相比于RhinoCommmon阉割了一些功能：Intersection/Loft/…</li>
      <li>支持的语言包括C# / Python / js.</li>
      <li>命名空间和RhinoCommon同构(C#/Python)</li>
    </ul>
  </li>
  <li><strong>python-rhino3dm的特性</strong>
    <ul>
      <li>rhino3dm库的使用不依赖于Rhino环境，但非要在Rhino环境中运行也是可以的(这和c#中两个库的互斥性略有一些不一样，很有意思…)</li>
      <li>
        <p>示例:</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># env: C:\...\env_name\Lib\site-packages # 安装rhino3dm的虚拟环境
</span><span class="kn">import</span> <span class="nn">rhino3dm</span>
<span class="p">...</span>
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
  <li><strong>一个BUG: 入参类型识别无效</strong>
    <ul>
      <li>
        <p>示例：期望得到1.0，输出为0.73，原因是把切向量识别为点坐标并触发了错误的构造函数</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">rhino3dm</span> <span class="k">as</span> <span class="n">rh</span>
<span class="n">arc3</span><span class="o">=</span><span class="n">rh</span><span class="p">.</span><span class="n">Arc</span><span class="p">(</span>
    <span class="n">pointA</span><span class="o">=</span><span class="n">rh</span><span class="p">.</span><span class="n">Point3d</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span> 
    <span class="n">tangentA</span><span class="o">=</span><span class="n">rh</span><span class="p">.</span><span class="n">Vector3d</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span>
    <span class="n">pointB</span><span class="o">=</span><span class="n">Point3d</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">arc3</span><span class="p">.</span><span class="n">Radius</span><span class="p">)</span>
</code></pre></div>        </div>
      </li>
      <li>
        <p>python使用Rhino(Rhinocommon)时没有这个问题
不论是否使用Rhinoinside加载都可以输出正确值，输出为1.0</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 在Rhino中作为脚本运行 / 在Rhino外启动rhinoinside
</span><span class="kn">import</span> <span class="nn">Rhino.Geometry</span> <span class="k">as</span> <span class="n">rg</span>
<span class="n">arc</span><span class="o">=</span><span class="n">rg</span><span class="p">.</span><span class="n">Arc</span><span class="p">(</span><span class="n">rg</span><span class="p">.</span><span class="n">Point3d</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span> <span class="n">rg</span><span class="p">.</span><span class="n">Vector3d</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">),</span><span class="n">rg</span><span class="p">.</span><span class="n">Point3d</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">arc</span><span class="p">.</span><span class="n">Radius</span><span class="p">)</span>
</code></pre></div>        </div>
      </li>
      <li>
        <p>C#-Rhino3dm也没有这个问题，输出为1</p>

        <div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">Rhino.Geometry</span><span class="p">;</span>
<span class="n">Arc</span> <span class="n">arc</span><span class="p">=</span><span class="k">new</span> <span class="nf">Arc</span><span class="p">(</span><span class="k">new</span> <span class="nf">Point3d</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">0</span><span class="p">,</span><span class="m">0</span><span class="p">),</span><span class="k">new</span> <span class="nf">Vector3d</span><span class="p">(</span><span class="m">0</span><span class="p">,</span><span class="m">1</span><span class="p">,</span><span class="m">0</span><span class="p">),</span><span class="k">new</span> <span class="nf">Point3d</span><span class="p">(</span><span class="m">1</span><span class="p">,</span><span class="m">1</span><span class="p">,</span><span class="m">0</span><span class="p">));</span>
<span class="n">Console</span><span class="p">.</span><span class="nf">WriteLine</span><span class="p">(</span><span class="n">arc</span><span class="p">.</span><span class="n">Radius</span><span class="p">);</span>
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
</ul>

<h5 class="chapter-heading-left">RhinoInside</h5>

<ul>
  <li><strong>RhinoInside的特性</strong>
    <ul>
      <li>在非Rhino环境的程序进程中加载RhinoCore并调用RhinoAPI.</li>
      <li>.NET和Python都有对应版本.</li>
      <li>.NET适用于net48/net7.0-windows等版本, 其中-windows不宜省去.</li>
      <li>.NET版本功能最全，例如通过windows的指针查找调用RhinoView.</li>
      <li>并完全不等同于在Rhino内运行script，例如不支持rhinoscriptsyntax.</li>
    </ul>
  </li>
  <li><strong>RhinoInside用于后端服务</strong>
    <ul>
      <li>在Windows系统启动一个.NET或Python的后端服务，并在服务中引用RhinoInside，就能得到一个基于RhinoCore的几何计算后端服务——这也是RhinoCompute的基本原理.</li>
      <li>
        <p>提供一个服务测试（python-flask）作为参考示例</p>

        <div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">request</span><span class="p">,</span> <span class="n">jsonify</span><span class="p">,</span> <span class="n">render_template</span>

<span class="kn">import</span> <span class="nn">rhinoinside</span>
<span class="n">rhinoinside</span><span class="p">.</span><span class="n">load</span><span class="p">()</span>

<span class="kn">import</span> <span class="nn">Rhino.Geometry</span> <span class="k">as</span> <span class="n">rg</span> <span class="c1"># 可以使用
</span><span class="kn">import</span> <span class="nn">rhinoscriptsyntax</span> <span class="c1"># 不受支持
</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>

<span class="c1"># 具体函数省略...
</span>
<span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
    <span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">'index.html'</span><span class="p">)</span>

<span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/calculate'</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s">'POST'</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">calculate_intersection</span><span class="p">():</span>
    <span class="p">...</span>
    <span class="k">return</span> <span class="n">jsonify</span><span class="p">({...})</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
    <span class="n">app</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="n">debug</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
  <li><strong>继发性Common版本冲突问题</strong>
    <ul>
      <li>RhinoInside自动从nuget加载的RhinoCommon版本与本地Rhino版本不一致，在编译/运行时报错</li>
      <li>
        <p>报错示例:</p>

        <div class="language-terminal highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="go">CSC : error CS1705: ... uses 
RhinoCommon, Version=8.7.24134.3001 ...
which has a higher version than referenced assembly 
RhinoCommon, Version=8.0.23304.9001 ...
</span></code></pre></div>        </div>
      </li>
      <li>
        <p>解决方法: 改为本地.dll引用, 避免自动从nuget载入包</p>

        <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;Reference</span> <span class="na">Include=</span><span class="s">"Rhino.Inside"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;HintPath&gt;</span>..\..\lib\Rhino.Inside.dll<span class="nt">&lt;/HintPath&gt;</span>
  <span class="nt">&lt;Private&gt;</span>true<span class="nt">&lt;/Private&gt;</span>
<span class="nt">&lt;/Reference&gt;</span>
</code></pre></div>        </div>
      </li>
    </ul>
  </li>
</ul>

<h5 class="chapter-heading-left">RhinoCompute</h5>

<ul>
  <li><strong>Compute的特性</strong>
    <ul>
      <li>基于Rhinoinside实现；rhinocompute ≈ rhinoinside + web service</li>
      <li>支持Grasshopper Definition (.gh)</li>
      <li>支持EndPoints自定义(原生2400+), 可以在.rhp加载时注册（嫌麻烦的话就直接自己写服务…）</li>
    </ul>
  </li>
  <li><strong>Compute</strong>
    <ul>
      <li>请求端</li>
      <li>请求端</li>
      <li>自行部署的服务端 run .rhp/.rhproj/.gh</li>
    </ul>
  </li>
</ul>

<h5 class="chapter-heading-left">Shim</h5>

<ul>
  <li><strong>Shim的特性</strong>
    <ul>
      <li>用于解除Rhinoceros相关开发中的重启动需求，即测试.rhp和.gha时需要反复重新启动Rhinoceros软件的问题</li>
      <li>在加载更多库的情况下，会出现一些莫名其妙的毛病，慎用…</li>
    </ul>
  </li>
  <li><strong>Shim的测试流程</strong>
    <ul>
      <li>dotnet build shim/TestRhpShim/<strong>Name</strong>.Shim.csproj</li>
      <li>Rhinoceros load shim/TestRhpShim/bin/Debug/net48/<strong>Name</strong>.Shim.rhp</li>
      <li>dotnet build shim/TestRhp/<strong>Name</strong>.TestRhp.csproj</li>
      <li>Rhinoceros run command <strong>Name</strong>+TargetCommandName</li>
    </ul>
  </li>
</ul>

<h5 class="chapter-heading-left">Paradigms @RhinoDev</h5>

<table>
  <thead>
    <tr>
      <th>Lang</th>
      <th>Format</th>
      <th>Name</th>
      <th>Note</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>C#</td>
      <td>.cs</td>
      <td>RhinoCommand</td>
      <td> </td>
    </tr>
    <tr>
      <td>C#</td>
      <td>.csproj</td>
      <td>RhinoPlugin</td>
      <td> </td>
    </tr>
    <tr>
      <td>C#</td>
      <td>.csproj</td>
      <td>Rhino Test</td>
      <td> </td>
    </tr>
    <tr>
      <td>C#</td>
      <td>.cs</td>
      <td>GrasshopperComponent</td>
      <td> </td>
    </tr>
    <tr>
      <td>C#</td>
      <td>.csproj</td>
      <td>GHAssembly</td>
      <td>include GHComponent</td>
    </tr>
    <tr>
      <td>C#</td>
      <td>.csproj</td>
      <td>GH2Plugin</td>
      <td> </td>
    </tr>
    <tr>
      <td>C#</td>
      <td><code class="language-plaintext highlighter-rouge">.cs-like</code></td>
      <td>GHScript</td>
      <td>ScriptInstance</td>
    </tr>
    <tr>
      <td>C#</td>
      <td>.cs</td>
      <td>RhinoCodeScript</td>
      <td> </td>
    </tr>
    <tr>
      <td>py</td>
      <td><code class="language-plaintext highlighter-rouge">.py-like</code></td>
      <td>GHScript</td>
      <td> </td>
    </tr>
    <tr>
      <td>py</td>
      <td>.py</td>
      <td>RhinoCommand</td>
      <td> </td>
    </tr>
    <tr>
      <td>py</td>
      <td>.py</td>
      <td>RhinoCodeScript</td>
      <td> </td>
    </tr>
    <tr>
      <td>-</td>
      <td>.rhproj</td>
      <td>ScriptPlugin</td>
      <td> </td>
    </tr>
  </tbody>
</table>

<ul>
  <li>GH｜ScriptInstance(类/电池)
    <ul>
      <li>LANG: C#</li>
      <li>LANG: Python</li>
    </ul>
  </li>
  <li>GH｜Component(类/文件) - Assembly(项目模板)
    <ul>
      <li>LANG: C#
调试不是特别方便，要用的话需要再研究和建构(比如.cs-.csproj-consoleapp-rhinoinside)</li>
    </ul>
  </li>
  <li>RH｜Scripting
    <ul>
      <li>LANG: C#</li>
      <li>LANG: Python</li>
    </ul>
  </li>
  <li>RH｜Command(类/文件) - Plugin/Assembly(项目模板) - Test(项目模板)
    <ul>
      <li>LANG: C#
    C# Command是单独的.cs文件，可以是某个插件Plugin中的一个命令Command
    Plugin是Rhino插件的项目模板，体现为.csproj文件和对应的目录，编译后为.rhp文件
    Test是Rhino插件测试的项目模板，体现为.csproj文件和对应的目录，编译后为可执行文件</li>
      <li>LANG: Python
    Python对项目结构的要求相对灵活，Command要求单个文件遵循模板并存储在特定目录，没有Plugin和Test项目模板。Command的运行机制和Scripting没有很大区别</li>
    </ul>
  </li>
  <li>几何数据结构/几何计算/几何可视化…三者关系/分离看待的必要性/在rhino中产生混淆的原因/…</li>
</ul>]]></content><author><name>HU Qian</name><email>huqian.archi@outlook.com</email></author><category term="技术分享" /><summary type="html"><![CDATA[]]></summary></entry><entry><title type="html">Gen Paradigm</title><link href="https://blog.archifrog.com/2024-11-11/gen-paradigm" rel="alternate" type="text/html" title="Gen Paradigm" /><published>2024-11-11T00:00:00+00:00</published><updated>2024-11-11T00:00:00+00:00</updated><id>https://blog.archifrog.com/2024-11-11/gen-paradigm</id><content type="html" xml:base="https://blog.archifrog.com/2024-11-11/gen-paradigm"><![CDATA[<div class="citation-simple">
    <a class="in-text-icon" href="https://d.wanfangdata.com.cn/thesis/Ch1UaGVzaXNOZXdTb2xyOVMyMDI1MTIyOTE1MzQ0MhIJRDA0MDg1Nzc3Gggybnh2dGMydw%3D%3D" target="_blank">
        <i class="fa-solid fa-paperclip fa-fw"></i>
        引用 胡潜. 走道式组合主导的建筑体量集合生成研究--以高校生活区为例[D]. 江苏:东南大学,2024.
    </a>
</div>

<!-- <div class="citation-bubble">
    <div class="citation-icon">
        <a>
            <i class="fa-solid fa-book"></i>
        </a>
    </div>
    <div class="citation-content">
        <a href='https://d.wanfangdata.com.cn/thesis/Ch1UaGVzaXNOZXdTb2xyOVMyMDI1MTIyOTE1MzQ0MhIJRDA0MDg1Nzc3Gggybnh2dGMydw%3D%3D' target="_blank">胡潜. 走道式组合主导的建筑体量集合生成研究--以高校生活区为例[D]. 江苏:东南大学,2024.</a>
    </div>
</div> -->

<hr />

<p class="plainpassage-brief">
在建筑与城市设计领域，计算机辅助设计已从传统的绘图工具演变为能够参与甚至驱动形态生成的重要力量。生成设计作为其前沿方向，旨在通过算法与规则，自动化或半自动化地探索设计解空间，为设计师提供多样、合理且优化的方案选项。其核心在于将设计问题转化为计算机可处理、可运算的模型。本文旨在梳理生成设计中几种关键的技术路径，主要围绕如何表示设计对象（数据结构）、如何定义生成逻辑（规则系统）以及如何求解复杂问题（通用求解）三个层面展开，为相关研究与实践提供参考。</p>

<h5 class="chapter-heading-left">数据结构</h5>

<p>将城市中的形态要素表示成数据是运用计算机程序来推动设计的基础。在此转化过程中，一些经典的数据结构可以供参考使用。</p>

<p>离散格网系统将空间划分为离散的格网单元，并通过变量(0,1)描述格网是否被占据，在精简数据结构的同时一定程度上顾及了建筑固有的“模数”特征。在划分方式中，等距的正交划分最为常见，格网单元的秩序能够借助各坐标轴向的秩序组合而成；非正交的划分方式也是可实现的，现有研究能够在二维空间中实现可变形模板对复杂轮廓形态的填充，形成拓扑连接关系合理的建筑平面图。在对马赛公寓设计过程的数字化诠释中，走道被看作是离散格网中一种固定形状的模板；在中小学的生成设计研究中，走道被描述成一系列连通的格网单元。</p>

<p>空间坐标系将空间中点的位置用它在相互垂直的各个坐标轴上的投影表示出来，再由此衍生出线、面、体的各种描述方式。例如用一系列点坐标形成封闭多段线就能够描述二维平面上的地块、建筑轮廓、房间等封闭区域。坐标系和离散格网的重要差别是没有“占据”的基本概念，形态要素的表达相对自由，向量的运算能够帮助建筑师执行许多“空间操作”。在基于语法规则的生成设计中，空间直角坐标系几乎是默认选项；在一些基于搜索的方法中，运用空间直角坐标系来描述点线面体也是可行的，但有时会使问题解空间过大从而影响搜索效率。</p>

<p>“顶点-边”系统能够用顶点和边两个抽象概念来描述现实空间中的许多问题。这一系统本质上是图结构，强调的是顶点之间的连接关系，也因此常常被用于建筑设计中的拓扑关系描述，如建筑中房间的连接关系；然而，顶点和边都可以携带附加信息，在许多应用中携带位置信息的顶点实质上超越了一般图结构中顶点的含义，具有了拓扑关系和空间位置的双重性质，相当于一组具有特定拓扑关系的“点-线段”。在空间坐标系中运用“顶点-边”系统来描述走道系统也是一种非常有效的策略，如中小学生成设计中的走道系统表示。</p>

<h5 class="chapter-heading-left">规则系统</h5>

<p>在生成设计中，规则系统是一种通过执行规则来生成形态结果的机制。下文主要介绍三类对本研究有帮助的规则系统建立方式，包括将建筑师自上而下的操作转译为程序规则，将已有的几何原型方法适配到建筑学问题上，以及通过分布在多智能体中的规则自下而上地生成形态结果。</p>

<p>生成形态的一种方法是将建筑师操作形态的某些规则转译成代码，通过执行代码得到形态结果。由于建筑师的职业习惯通常不是按照一套规则来“生成”形态结果，这种规则的总结和编写需要具有建筑学知识的人员根据形态结果，结合法规和设计经验，后发地总结出来。</p>

<p>这种从案例中后发总结操作性规则的研究很早就出现了，例如20世纪对帕拉奥迪别墅语法的研究；这一研究实质上已经形成了多步骤可执行的规则系统，能够生成帕拉奥迪别墅的“仿制品”。随着计算机技术的发展，这种规则系统得以被自动执行和充分可视化。Duarte将总结出的规则编写成程序，并运用此程序为用户定制房屋平面；Mahyar将美国住宅建筑中的特定类型转化为形状语法，生成的建筑具有共同风格特征；陈宇龙从南京城南传统建筑中提取规则，并实现了面向异形地块的适应性生成。</p>

<p>除了建筑师的经验总结外，一些计算几何中的原型方法也能为生成规则的编写提供很大便利。将这些原型适配到合适的建筑学问题上，或基于它们的原理来编写新的规则，能够充分利用已有知识解决复杂问题，可以看作是扩充了建筑设计的知识范围。</p>

<p>在城市地块的剖分研究中，Vanegas等总结并提出了生成设计中常用的几何原型方法，包括Voronoi方法，最小面积包围盒方法，偏移和骨架方法等。另一个重要的几何原型方法是向量场。向量场是空间中从点到方向向量的映射，能够建立（具有方向的）形态要素所在位置和朝向之间的关联。走道通常具有明显的方向性，由走道支配的形态与场地本身的形状具有相互关联，通过向量场来间接控制走道的形态是可选方法之一。综合场地要素得到向量场的方法包括径向基函数法，通过数学规划求解最小方差等；参数化建模软件Grasshopper中也提供了向量场相关的功能。</p>

<p>多智能体系统是一种特殊的规则组织方式。将规则分布在不同的“个体”中，由这些个体自组织地执行规则，对环境做出反应，就形成了自下而上执行规则的系统范式。这种执行规则的方式能够弥补一般规则系统在自上而下描述某一过程的不完备性，经个体之间的相互作用和整个系统的逐帧迭代，“涌现”出可能符合建筑师评价标准的形态结果。除了规则制定外，多智能体系统建立的重要步骤是确定代理的对象。已有研究中的多智能体能够代理强排中的建筑单体，建筑内的房间，建筑构件等。对本研究而言，在“顶点-边”系统中用多智能体代理顶点和边，在分散的一系列建筑中用多智能体代理建筑个体都是可能有效的建模方式。</p>

<h5 class="chapter-heading-left">通用求解</h5>

<p>除了运用建筑学知识制定规则和流程外，将建筑学问题表示成特定的形式，运用在各个学科广泛适用的元启发式算法进行求解，也是生成建筑体量的有效方法。进化算法在建筑学领域就有较多的应用，例如解决功能拓扑关系限定下的布局问题，又如处理特定目标导向下的建筑形态优化。这类算法在数据结构本身对解空间有充分限定的情况下能够发挥良好的优化作用，但并不能在多重复杂约束条件下表现出同样的效果（可能给出不满足全部约束的解）。</p>

<p>近年来，随着通用求解器的迅猛发展，上述算法应用范式受到了一定挑战。以Gurobi等商业软件为代表的数学规划求解器能够在短时间内将表示成特定形式的问题通过内置的算法流程高效求解，得到可行解或优化解。在应用这种方法时，应用方程和不等式描述问题是主要任务，求解过程中的算法应用并不需要使用者关心；同时，求解器对多重约束条件也有较好的解决能力，得到的解一定在可行域内，在问题规模可控的情况下能够在有限时间内给出答案。这种应用范式中，求解的通用性得到了很大的提升。它的应用使得处理约束条件较多的城市设计问题更为便捷，例如居住建筑的排布。</p>

<p>然而，这种方法的局限性也是明显的。一方面，通用求解器在问题规模扩大到一定程度时将无法在短时间内完成解算；另一方面，现有求解器对线性规划问题和一些二次规划问题有良好的表现，因而对问题的表示本身提出了要求，即不适宜出现更为复杂的表达式和方程。</p>

<h5 class="chapter-heading-left">总结</h5>

<p>生成设计研究与实践的推进，关键不在于追求某种技术的极致，而在于回归到细分、具体的建筑设计问题本身。设计师或研究者需要首先清晰界定一个“细小而聚焦”的真实业务问题——例如特定类型的空间布局优化、特定规范下的形态生成，或特定流线组织的自动化探索。在此基础上，明智地选取、创造性地组合不同的技术方法（mixed-paradigm）。</p>

<p>对建筑设计为主业的研发团队而言，相比于追逐技术热点，应更加注重这种问题导向、务实整合的策略。通过将宏大的愿景分解为一系列“简明而落实”的子问题，并为之匹配恰当的技术工具组合，生成设计才能真正跨越理论与实践的鸿沟，在具体的业务场景中持续产生扎实、可靠且富有洞见的设计解决方案。</p>

<div class="figure-full">

    
    <img src="https://workhub.oss-cn-shanghai.aliyuncs.com/picture/general/lecture-ppt/gen-paradim-2-2.png" alt="" />
    <p>
        <i class="fa-solid fa-caret-up"></i>
        本人在华建集团上海院所作相关学术分享
    </p>
    
</div>]]></content><author><name>HU Qian</name><email>huqian.archi@outlook.com</email></author><category term="技术分享" /><summary type="html"><![CDATA[引用 胡潜. 走道式组合主导的建筑体量集合生成研究--以高校生活区为例[D]. 江苏:东南大学,2024.]]></summary></entry><entry><title type="html">Mathe Prog</title><link href="https://blog.archifrog.com/2022-02-02/mathe-prog" rel="alternate" type="text/html" title="Mathe Prog" /><published>2022-02-02T00:00:00+00:00</published><updated>2022-02-02T00:00:00+00:00</updated><id>https://blog.archifrog.com/2022-02-02/mathe-prog</id><content type="html" xml:base="https://blog.archifrog.com/2022-02-02/mathe-prog"><![CDATA[<hr />

<p class="plainpassage-brief">本文将介绍数学规划方法在建筑设计问题中的应用。

数学规划（Mathematical Programming）是一类通过构建数学模型并求解最优解的方法，核心是在给定约束条件下最大化或最小化目标函数。随着计算机技术的发展，其在复杂系统优化中的优势日益凸显。建筑设计作为融合功能、美学、经济与可持续性的多目标决策过程，常面临空间布局、资源分配、性能优化等复杂问题。数学规划通过量化目标与约束，为建筑设计提供高效决策支持，成为探索设计可能、提升设计效率的重要工具。</p>

<p><code class="language-plaintext highlighter-rouge">编辑中...</code></p>

<h5 class="chapter-heading-left">问题形式</h5>

<p>数学规划的常见形式包括：</p>
<ul>
<li>整数规划（Integer Programming, IP）：变量需取整数值，适用于离散决策场景</li>
<li>混合整数线性规划（Mixed-Integer Linear Programming, MILP）：部分变量为整数，目标函数与约束均为线性，计算效率较高</li>
<li>混合整数二次规划（Mixed-Integer Quadratic Programming, MIQP）：目标函数含二次项（如平方误差）</li>
<li>非线性规划（Nonlinear Programming, NLP）：目标或约束含非线性项</li>
<li>多目标规划（Multi-objective Programming）：同时优化多个冲突目标，输出 Pareto 最优解集供决策者权衡。</li>
</ul>
<p>对于建筑设计问题而言核心在于</p>
<ul>
<li>是否能用格网填充表示?绝大多数问题更适宜用在。在不使用“填充”定义问题时，离散变量实质上是连续变量的一种特殊取样，并非真正的离散建模</li>
<li>能否用纯线性方式建模?</li>
</ul>

<h5 class="chapter-heading-left">通用求解器</h5>

<p>Gurobi
SCIP 开源，有pyscipopt，但没有C#接口。
…</p>

<table border="1" cellpadding="5" cellspacing="0">
  <thead>
    <tr>
      <th><strong>求解器</strong></th>
      <th><strong>特点</strong></th>
      <th><strong>接口支持</strong></th>
      <th><strong>适用场景</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Gurobi</strong></td>
      <td>商业求解器，速度快、稳定性强，支持 LP/MIP/MIQP/NLP 等全类型问题，提供免费学术许可。</td>
      <td>Python/C++/Java/C#/MATLAB 等主流语言</td>
      <td>...</td>
    </tr>
    <tr>
      <td><strong>CPLEX</strong></td>
      <td>商业求解器，与 Gurobi 性能相当，擅长 MIP 问题，提供可视化建模工具。</td>
      <td>类似 Gurobi，支持 C#/Python 等</td>
      <td>...</td>
    </tr>
    <tr>
      <td><strong>SCIP</strong></td>
      <td>开源求解器，支持 MIP/NLP/CP 等，灵活性强，可通过插件扩展算法。</td>
      <td>提供 pyscipopt（Python）、C 接口；无官方 C# 接口</td>
      <td>...</td>
    </tr>
    <tr>
      <td><strong>GLPK</strong></td>
      <td>轻量级开源求解器，适合教学与简单 LP/MIP 问题，计算效率较低。</td>
      <td>支持 C/Python/Java 等</td>
      <td>...</td>
    </tr>
    <tr>
      <td><strong>COIN-OR</strong></td>
      <td>开源项目集合，包含 CBC（MIP 求解器）、Clp（LP 求解器）等，可定制化高。</td>
      <td>多语言接口，社区活跃</td>
      <td>开源项目集成</td>
    </tr>
  </tbody>
</table>

<h5 class="chapter-heading-left">应用方向</h5>
<p>…
<!-- PeterWonka
中科大2018
飚门系列
野人2021系列 --></p>

<h5 class="chapter-heading-left">一个实例</h5>

<p><strong>问题描述</strong></p>

<ul>
  <li>给定w×h的有限格网容器(Container)、出发点（绿）、目标点（红），求连接出发点和各个目标点的最短路径</li>
</ul>

<p><strong>求解原理</strong></p>

<ul>
  <li>一般地，在图论问题中，由系列顶点和边（对弧）构成的简单图中可以通过给点和边赋值的方法求解最小路径问题；格网中的最小路径问题更为特殊，将一般情形中任意的相邻关系和距离值用格网的方式明确定义出来。</li>
  <li>简单图的最短路径求解问题中，需要两组赋值来定义连通关系：一组是边（对弧）赋值，用每边所包含一弧的赋值（图论中通常称作出入度）表示该弧对应方向上存在连通关系；一组是对顶点赋值，出发点和目标点分别赋予正负值，其余点赋予0值；而后在两组值之间建立出、入度方程，以顶点值为已知量，边值为求解变量，再求取路径最小值。</li>
  <li>在求取路径最小值的问题中，没有路径可以看作路径最短的极端情形。此时可以看作所有边（弧）被赋予0值。当我们需要连通出发点和目标点时，给出发点和目标点赋予非零值，以方程关系传递非零值，而方程又仅建立在容许连通的点边之间，也就起到了标识连通关系的作用。</li>
  <li>当我们容许目标点被路径穿越、容许路径分岔时，方程关系将变得更为复杂。可将每个目标点的非0值设定为1，则（最短路径解中）所有边（弧）上的值可以追溯到某一目标点上（否则可以用反证法证明非优）。上述两种情况时均可以看作某一边（弧）上的值同时追溯多个目标点，因此边（弧）的赋值可能是小于目标点数量的任意整数。</li>
</ul>

<p><strong>模型构建</strong></p>

<ul>
  <li>
    <p>变量</p>

    <ul>
      <li>
        <p>水平方向“的BINARY弧变量 $rf[i][j]，lf[i][j]，(0&lt;i≤w+1，0&lt;j≤h)$</p>
      </li>
      <li>
        <p>竖直方向的BINARY弧变量 $uf[i][j]，df[i][j]，(0&lt;i≤w，0&lt;j≤h+1)$</p>
      </li>
      <li>
        <p>水平方向“的INTEGER边权重值 $rlw[i][j]，(0&lt;i≤w+1，0&lt;j≤h)$</p>
      </li>
      <li>
        <p>竖直方向“的INTEGER边权重值 $udw[i][j]，(0&lt;i≤w，0&lt;j≤h+1)$</p>
      </li>
    </ul>
  </li>
  <li>
    <p>目标</p>

    <ul>
      <li>路径总长度  $Minimize（\displaystyle\sum rf[i][j]+\displaystyle\sum lf[i][j]+\displaystyle\sum uf[i][j]+\displaystyle\sum df[i][j]）$</li>
    </ul>
  </li>
  <li>
    <p>约束</p>

    <ul>
      <li>
        <p>目标点入度为1，出度为0（入度-出度=1）
$\forall$ 目标点$（i，j）$，
$rlw[i+1][j]（lf[i+1][j]-rf[i+1][j]）$
$+rlw[i][j]（rf[i][j]-lf[i][j]）$
$+udw[i+1][j]（df[i+1][j]-uf[i+1][j]）$
$+udw[i][j]（uf[i][j]-df[i][j]）$$=1$</p>
      </li>
      <li>
        <p>出发点入度为0，出度为正整数（入度-出度=负整数）</p>

        <p>$\forall$ 出发点$（i，j）$，
$rlw[i+1][j]（lf[i+1][j]-rf[i+1][j]+rlw[i][j]（rf[i][j]-lf[i][j]）+udw[i+1][j]（df[i+1][j]-uf[i+1][j]）+udw[i][j]（uf[i][j]-df[i][j]&lt;0$</p>
      </li>
      <li>
        <p>普通点入度、出度相等（入度<em>权重-出度</em>权重=0）</p>

        <p>$\forall$ 普通点$（i，j）$，
$rlw[i+1][j]（lf[i+1][j]-rf[i+1][j]）$
$+rlw[i][j]（rf[i][j]-lf[i][j]）$
$+udw[i+1][j]（df[i+1][j]-uf[i+1][j]）$
$+udw[i][j]（uf[i][j]-df[i][j]）$$=0$</p>
      </li>
      <li>
        <p>超出容器的边（弧）权重为0
$rfw[i][j]=0$，$（i=0$ or $w+1）$
$udw[i][j]=0$，$（j=0$ or $h+1）$</p>
      </li>
    </ul>
  </li>
</ul>]]></content><author><name>HU Qian</name><email>huqian.archi@outlook.com</email></author><category term="技术分享" /><summary type="html"><![CDATA[]]></summary></entry></feed>