基于约束关系的图表设计

news2024/10/5 21:18:18

标准的基于 GUI 的图形设计工具仅支持有限的“对齐向导”风格的定位,具有基本的对象分组系统,并实现对齐或分布对象的原始功能。这些工具没有办法记住对象之间的约束和关系,也没有办法定义和重用抽象。我一直不满意现有的设计工具,尤其是用于创建图形和图表的工具,因此我一直在开发一个名为 Basalt 的新系统,它符合我的想法:在关系和抽象方面。

在这里插入图片描述

1、Basalt简介

Basalt 以特定领域语言 (DSL) 的形式实现,与 Illustrator 和 Keynote 等基于 GUI 的设计工具截然不同。它也与 D3.js、TikZ 和diagrams等库/语言有很大不同。 Basalt 的核心是基于约束:设计者根据关系指定图形,这些图形编译成约束,使用 SMT 求解器自动求解以产生最终输出。这允许设计师根据关系来指定图纸,例如“这些对象水平分布,它们之间的空间比例为 1:2:3”。约束也是 Basalt 如何支持抽象的一个关键方面,因为约束可以很好地组合。

在这里插入图片描述

在过去的几年里,我一直在断断续续地试验这个概念。 Basalt远未完成,但探索已经取得了一些有趣的结果。 该原型非常有用,我用它制作了最新研究论文和演示文稿中的所有图表。

如果你想了解 Basalt 背后的核心思想,请查看哲学部分。 如果想了解我使用 Basalt 设计真实人物的经验,请跳至案例研究部分。 如果想了解如何使用梯度下降来求解图形,请转到梯度下降部分。

2、Basalt背后的哲学

Basalt 的编程模型如下。 设计师编写的程序可以生成根据关系描述的图形。 这些关系被编译成约束,然后自动求解。

Basalt 是嵌入在通用编程语言中的 DSL,因此它继承了对功能抽象、类等的支持。 它基于约束的方法是支持很好组合的抽象的关键。

3、利用几何关系绘图

Basalt 的编程模型允许根据对象之间的关系来指定绘图。 用于图形设计的基于 GUI 的标准工具不支持此功能。 它们具有有限的“对齐向导”定位风格,以及基本的对象分组系统和用于对齐或分布对象的基本功能。 他们不根据原始对象和约束对图形进行编码; 相反,像对齐对象这样的动作会强制更新位置,这是底层表示存储的内容。 CAD 工具支持约束,但不适用于图形设计。

考虑具有以下描述的图形。 “有一块浅灰色的帆布。 中间是一个蓝色圆圈,直径是画布宽度的一半。 圆圈内是一个红色正方形。” 图片看起来像这样:

在这里插入图片描述

在不使用约束的情况下,在 Basalt 中生成此类图形的代码如下所示:

width = 300
height = 300

bg = Rectangle(0, 0, width, height,
    style=Style({Property.fill: RGB(0xe0e0e0)}))
circ = Circle(x=150, y=150, radius=75,
    style=Style({Property.stroke: RGB(0x0000ff), Property.fill_opacity: 0}))
rect = Rectangle(x=96.97, y=96.97, width=106.06, height=106.06,
    style=Style({Property.stroke: RGB(0xff0000), Property.fill_opacity: 0}))

g = Group([bg, circ, rect])

c = Canvas(g, width=width, height=height)

设计师必须弄清楚一切都在哪里,手动计算锚点和大小。 相反,有了约束,设计师可以写下形状之间的关系,该工具将解决这个问题:

width = 300
height = 300

bg = Rectangle(0, 0, width, height, style=Style({Property.fill: RGB(0xe0e0e0)}))
circ = Circle(style=Style({Property.stroke: RGB(0x0000ff), Property.fill_opacity: 0}))
rect = Rectangle(style=Style({Property.stroke: RGB(0xff0000), Property.fill_opacity: 0}))

# The Group constructor takes two arguments: the first is a list of objects,
# and the second lists additional constraints, equations that relate the
# objects to one another

g = Group([bg, circ, rect], [
    # circle is centered
    circ.bounds.center == bg.bounds.center,

    # circle diameter is 1/2 of canvas width
    2*circ.radius == width/2,

    # rectangle is centered on circle
    rect.bounds.center == circ.bounds.center,

    # rectangle is a square
    rect.width == rect.height,

    # rectangle is circumscribed
    rect.width == circ.radius*2**0.5
])

c = Canvas(g, width=width, height=height)

每个图元都知道如何根据其内部属性计算自己的边界:例如,圆的边界是 (x-r, y-r)(x−r,y−r) 到 (x+r, y+r)(x+ r,y+r),并且一个组的界限是根据单个元素界限的最小值/最大值来定义的。允许属性和边界是符号表达式:例如在上面的代码中,圆没有给出具体的圆心或半径,因此这些属性各自自动初始化为一个新的 Variable(),然后边界取决于这些变量。当约束求解器运行时,它们只会被分配一个具体的值。

Basalt 基于约束的方法允许设计师根据关系进行思考,并在图纸本身的规范中表达这些关系,而不是让它们隐含并由设计师手动解决。

上图可以在 Illustrator 中绘制,但可能需要拿出铅笔和纸来计算物体的位置。手动解决设计人员考虑但未在工具中编码的隐式约束(这是设计人员目前对现有程序所做的)是痛苦的且不可扩展的。

如果图形设计稍微改变一下,例如圆形要刻在矩形中怎么办?使用 Illustrator,需要手动重新计算所有位置;使用 Basalt,只需一行代码:

-  # rectangle is circumscribed
-  rect.width == circ.radius*2**0.5
+  # circle is inscribed
+  rect.width == circ.radius*2

在这里插入图片描述

对于一个简单的图形,手动进行这样的更改可能是可行的,但是如果图形有数百个对象怎么办? 使用 Illustrator,根据设计师头脑中的限制手动将所有对象精确定位到它们需要去的位置会失控。 在 Basalt 中,约束求解器完成了确定对象精确位置的艰巨工作,并且扩展性很好(例如,这个图形有数百个对象)。

3、支持抽象

约束导致支持抽象的自然方式,这是设计复杂图形所必需的另一个关键方面。 子组件可以根据它们的部件和内部约束来指定。 当这些组件被实例化用于顶级图(或更高级别的组件)时,约束可以简单地合并在一起。

假设我们想要一个外接正方形的抽象,然后有四个,排列成 2x2 网格,填满画布。 首先,我们可以定义抽象,一个由圆形和矩形组成的组,具有一些内部约束:

def circumscribed_square():
    circ = Circle(style=Style({
        Property.stroke: RGB(0x0000ff),
        Property.fill_opacity: 0
    }))
    rect = Rectangle(style=Style({
        Property.stroke: RGB(0xff0000),
        Property.fill_opacity: 0
    }))
    return Group([circ, rect], [
        # rectangle is centered on circle
        rect.bounds.center == circ.bounds.center,
        # rectangle is a square
        rect.width == rect.height,
        # rectangle is circumscribed
        rect.width == circ.radius*2**0.5
    ])

然后,我们可以多次实例化它,并添加它们排列在 2x2 网格中且大小相同的约束:

c1 = circumscribed_square()
c2 = circumscribed_square()
c3 = circumscribed_square()
c4 = circumscribed_square()

g = Group([c1, c2, c3, c4], [
    # arranged like
    # c1 c2
    # c3 c4
    c1.bounds.right_edge == c2.bounds.left_edge,
    c3.bounds.right_edge == c4.bounds.left_edge,
    c1.bounds.bottom_edge == c3.bounds.top_edge,
    # and all the same size
    c1.bounds.width == c2.bounds.width,
    c2.bounds.width == c3.bounds.width,
    c3.bounds.width == c4.bounds.width,
])

最后,我们可以表达图形填充画布的约束:

width = 300
height = 300

bg = Rectangle(0, 0, width, height, style=Style({Property.fill: RGB(0xe0e0e0)}))

top = Group([bg, g], [
    # figure is centered
    g.bounds.center == bg.bounds.center,
    # and fills the canvas
    g.bounds.height == bg.bounds.height
])

c = Canvas(top, width=width, height=height)

渲染时,此代码生成下图:
在这里插入图片描述

4、使用约束作为装配语言

约束不一定是最终用户应该直接编写的内容,但约束构成了一种很好的装配语言:根据 Basalt 的约束可以很容易地表达更高层次的几何概念。 例如,表示一组对象是顶部对齐的就这么简单:

def aligned_top(elements):
    top = Variable() # some unknown value
    return Set([i.bounds.top == top for i in elements])

其他概念,如水平或垂直分布的对象、相同的宽度或高度,或插入另一个对象内,也可以编译为约束。 Basalt 提供了一些更高层次的几何图元,用户可以定义自己的。

5、实例研究

  • 敌对的乌龟

这是我为一篇论文制作的图,使用Basalt 重新创建:
在这里插入图片描述

该图显示了许多图像,由边框颜色给出的这些图像的分类。 这个图形的 Basalt 代码定义了两个抽象,它们组成了这个图形:

def bordered_image(source: str, border_color, border_radius):
    image = Image(source)
    border = Rectangle(style=Style({Property.fill: border_color}))
    return Group([border, image], [
        inset(image, border, border_radius, border_radius)
    ])

def grid(elements: List[List[Element]], spacing):
    rows = [Group(i) for i in elements]
    return Group(rows, [
        # all elements are the same size
        same_size([i for row in rows for i in row.elements]),
        # elements in rows are distributed horizontally
        Set([distributed_horizontally(row, spacing) for row in rows]),
        # and aligned vertically
        Set([aligned_middle(row) for row in rows]),
        # rows are distributed vertically
        Set([distributed_vertically(rows, spacing)]),
        # and aligned horizontally
        aligned_center(rows)
    ])

这个图非常简单,可以用 Illustrator 等传统工具绘制它,但以编程方式绘制它的好处不仅仅是避免在基于 GUI 的工具中手动布置图形的烦恼。 该论文有 5 个这种风格的图形,具有不同的图像和大小:使用代码允许我们对这些图形进行参数化,并只完成设计图形的工作一次。 此外,这些数字本来是要写在纸上的,这是一种相当受限的格式:例如,我们的数字的宽度是固定的。 我们需要确定图形参数,例如网格尺寸、边框大小和图像大小,这将使图形具有可读性,并且让代码生成图形可以轻松探索此参数空间。

论文中的原始图形实际上是在没有Basalt的情况下制作的,因为当时不存在Basalt。 相反,我编写了直接绘制输出图像像素的 Python 代码,但 Basalt 代码要好得多。

  • Robust ML 徽标

我和我的兄弟 Ashay 为 Robust ML 设计了徽标。 从盾牌和神经网络的一般概念开始,Ashay 在纸上画了几个草图:
在这里插入图片描述

接下来,我在 Illustrator 中绘制了徽标草图。 即使在我们有了徽标的基本想法之后,还是需要进行大量迭代才能弄清楚细节,包括选择神经网络中的层数、每层中的节点数以及节点之间的间距给定层。 某些更改很容易,例如使用 Illustrator 的重新着色图稿功能调整颜色。 其他变化非常痛苦; 例如,添加一个节点需要大量的手工劳动,因为它需要移动节点和线以及创建和定位一个新节点和许多新线。 累积起来,在标志的几十次迭代中,我花了几个小时在 Illustrator 中移动形状。

从那以后,我用 Basalt 重新制作了标志,在实时预览工具的帮助下探索参数空间要容易得多。
在这里插入图片描述

这是最终输出的样子:
在这里插入图片描述

  • 架构图

这是在 TikZ 中制作的图,来自最近一篇论文的草稿:
在这里插入图片描述

这是上面 TikZ 图的代码。 它使用大量硬编码位置,使用像 \draw [boxed] (-1,-2.5) rectangle (16.5,4) 这样的命令。 使用 TikZ 很难使图形看起来特别漂亮。 对于论文的已发布版本,我使用 Basalt 设计了图形,在此过程中还稍微更改了样式:

在这里插入图片描述

该图定义并使用了许多建立在 Basalt 图元之上的新抽象,包括:

  • Component: 一个盒子,里面有居中的文本
  • Peripheral:一个圆角的盒子,里面的文字居中
  • Wiring:一堆线段,带有可选的箭头,连接两点,带有可选的标签文本

描述这些抽象概念一次,然后多次使用它们会带来愉快的图形设计体验。 比如上图中Wiring定义了一次,实例化了11次。 当然,整个图表都是使用关系指定的。 诸如"Kernel domain"文本位于其区域中心之类概念很容易表达。 该代码使用了许多几何图元,表达了组件的输入/输出沿边缘均匀分布等概念。

  • SoC图

这是同一篇论文中的另一幅图:
在这里插入图片描述

论文中的图表共用抽象以保持一致的外观; 这个图使用了上图中的 Component和 Wiring抽象。 基于约束的设计特别有助于设计该图的某些方面,像底部箭头的间距这些。 例如,让箭头沿框的整个宽度均匀分布看起来很糟糕; 这很容易测试,只需要对 I/O 箭头抽象做一点小改动:

-  distributed_horizontally(arrows.elements, periph_io_spacing),
-  arrows.bounds.center.x == periph.bounds.center.x
+  distributed_horizontally(arrows.elements),
+  arrows.bounds.left == periph.bounds.left,
+  arrows.bounds.right == periph.bounds.right

基于约束的设计,连同 Basalt 的实时预览工具,可以轻松选择其他参数,使它们看起来适合最终图形。

在这里插入图片描述

在代码中实现此图还可以轻松完成诸如匹配图和论文中文本之间的字体大小之类的操作。 在外部工具中设计图形时,图形通常会在事后缩放以适合纸张,但这会影响有效字体大小。 使用 Basalt,可以很容易地设计整体图形,然后适当地调整它的大小,以便在不重新缩放的情况下将其包含在论文中,最后调整图形参数,使其可以使用与论文相同的字体大小。

  • 架构图动画

我需要制作架构图的简化版本以供演示。此外,我需要在多张幻灯片上制作动画以突出显示和解释不同的方面。

我开始在 Keynote 中实现演示文稿和图形,但是在 Keynote 中设计图形有点痛苦,因为对象重叠,而且构建阶段的细节也不同。我尝试在一张幻灯片上做所有事情,但我遇到了 Keynote 动画系统的限制(例如,不可能让一个对象出现,然后消失,然后再次出现)。我尝试复制一些对象来解决这个问题,但很快就失控了,即使使用 Keynote 的对象列表也是如此。我尝试将构建拆分为多张幻灯片,但随后进行全局编辑变得很烦人。

最后,我改用 Basalt 作为图形(并将演示文稿切换为 Beamer)。设计一个细节因构建阶段而异的图形很简单:
在这里插入图片描述

基于构建阶段更改的方面利用了 BUILD 变量,例如 reset_color = red if BUILD == 3 else black。 此 BUILD 变量是通过环境变量 BUILD = os.environ[‘BUILD’] 设置的,因此可以通过设置例如 BUILD=2 并渲染图形。

  • 不干涉图构建

同一个演示文稿还有另一个由一系列幻灯片组成的图:
在这里插入图片描述

它使用与上图相同的构建变量方法来编码基于构建阶段发生变化的方面,例如图中底部的分隔符:

labels = []
if BUILD >= 1: labels.append('Agent A runs')
if BUILD >= 2: labels.append('Deterministic start')
if BUILD >= 3: labels.append('Agent B runs')
if BUILD == 4:
    labels = ['Deterministic start']
delim = LabeledDelimiters(labels)

为了渲染构建的不同阶段,图形使用不同的变量设置进行渲染,例如 建造=3。

该图旨在匹配上图中设置的相同视觉语言。 这很容易通过与上图共享抽象来实现(此处使用略有不同的参数实例化,例如较低的线数)。

同样,Basalt 的实时预览工具有助于选择图形参数,这样图形看起来不错,字体大小与演示文稿中的其他图形匹配。
在这里插入图片描述

  • DFSCQ日志图

我想尝试从我没有写过的论文中重新创建一个复杂的图形。 原件是由该论文的一位作者在 Inkscape 中制作的。 Basalt 版本的目标不是创建像素完美的娱乐,而是使用 Basalt 构建抽象的方法,看看它如何扩展到复杂的图形。 这是一个并排比较,显示 Basalt 能够复制该图:
在这里插入图片描述

Inkscape 图是一大堆手动定位的对象,大概是通过一堆复制粘贴制作的。 另一方面,Basalt 图定义并使用了许多抽象,所有抽象都实现为构建在 Basalt 基元之上的类:

  • Layer :具有各种内容的堆叠水平框之一,例如 “日志API”
  • Blocks :一系列彩色矩形,例如 “activeTxn”标签右侧的块方括号,一个“[”or“]”形状
  • BlockList: 一个块列表,由一个开括号、以逗号分隔的一系列块和一个右括号组成,例如 “committedTxns”标签右侧的内容(使用 Blocks 和 Bracket)
  • LabeledDelimiters:对应于某物部分的标签,例如 在“磁盘日志”下面(这个抽象也用在上面的 Notary noninterference 图中)
  • DiskLog: 磁盘日志的内容,例如 在“磁盘日志”标签的右侧(使用块)
  • Explode: 显示图形一部分的一对虚线爆炸,连接某些堆叠层的子部分,例如 在“DiskLog”和“Applier”层之间
  • ArrowFan:呈扇形展开的箭头,例如 在“Applier”层

这个数字需要一些努力才能实现。 Basalt 的实时预览工具在处理这个图形时非常有用:更改代码后立即看到图形的更新对于构建这个复杂的图形至关重要。 滑块也有助于使布局与原始布局相匹配。 在保持其总体结构的同时调整参数并查看图形自身重绘是非常简洁的:
在这里插入图片描述

6、约束求解器

Basalt 允许设计人员根据关系和约束来指定图表,这些关系和约束归结为基于实变量的方程式。 Basalt 对这些方程式没有太多限制,这为用户提供了很大的灵活性,但它使底层实现更具挑战性,因为它必须自动求解这些方程式。 Basalt方程可以有诸如共轭和反共轭、最小/最大项和变量的乘积/商之类的东西,所以在一般情况下,不可能将方程转换成一些很好的形式,比如计算效率高的线性规划问题。 Basalt方程符合无量词非线性实数算术 (QFNRA) 的逻辑,因此至少可满足性是可判定的,但求解不一定会很快。

目前,Basalt 支持几种不同的方程求解策略。

  • Z3

当前默认使用 Z3 定理证明器,这是一个强大的 SMT 求解器,支持 QFNRA 等。 将来自 Basalt 的约束编码到 Z3 查询中很简单,在实践中,Z3 工作得很好。

  • 混合整数线性规划

Basalt 支持将约束子集编译为混合整数线性规划 (MILP)问题,这些约束使用线性实数算术以及一些操作(如最小/最大),然后使用 MILP 求解器求解,目前使用的是 Google 的OR-Tools 的CBC求解器。 Basalt 的 MILP 后端严格来说不如 Z3 后端通用,即使在它支持的查询上它似乎也比 Z3 慢,但实现起来很有趣。

  • 梯度下降

到目前为止,最没用但最有趣的方程求解器是基于梯度下降的。 从 Basalt 约束到可微损失函数有一个直接的转换,这个转换是合理的。 这意味着当且仅当原始约束可满足时,损失函数具有全局最小值0,并且当损失函数确实具有全局最小值 0 时,每个全局最小值都以直接的方式对应于原始约束的令人满意的分配变量。

当然,这并没有说明这个损失函数的特性,也没有说明它是否适合通过梯度下降进行优化。 但我还是继续实施了它,使用 TensorFlow 来处理计算导数的任务。

与其他方法不同,梯度下降迭代地计算解决方案,因此可以动画化图形的求解,结果非常有趣:
在这里插入图片描述

  • 解的唯一性

有时,用户生成的图形中的约束集有多个解;换句话说,这个数字没有完全约束。根据我的经验,这几乎总是表示图形代码中存在错误,因为用户不太可能有两个外观不同的图形,其中任何一个图形都可以接受。

Basalt 可以确定这种情况何时发生,因为它可以直接编码为 SMT 查询。如果原始约束集是 CC,它有一个解 M=(x 1 =v1 ∧x2 =v2 ∧⋯xn =vn) ,那么我们可以询问 SMT 求解器 C∧¬M 是否有解。如果新公式不可满足,则原解是唯一的,图形是完全约束的。在新公式可满足的情况下,SMT 求解器返回另一个有效解的具体示例。比较这两个解决方案可以帮助用户弄清楚图形约束不足的原因。

7、未来的工作

Basalt还有很多工作要做。

现在,它是 Python 中的嵌入式 DSL,而且这种语言有点笨拙。 Racket,一种用于构建编程语言的编程语言,可能是一个更好的平台。 Tej Chajed 和我目前正致力于构建一个更复杂的使用 Racket DSL的Basalt 版本。

我有兴趣探索的另一件事是拥有 Basalt 图形的可视化编辑器,这是 Basalt 方法和现有的基于 GUI 的工具之间的一种混合体,因为能够四处拖动对象通常很方便。 这可能涉及使用类似于 CAD 工具中使用的方法,或者可能更奇特的方法,例如 g9.js 中使用的技术,在代码及其可视化表示之间建立双向绑定。

8、结束语

从 1963年Ivan Sutherland 的 Sketchpad 开始,基于约束的设计领域进行了长期的研究。据我所知,大多数使用这些想法的工具都是基于 GUI 的 CAD 程序,而不是实用的图形设计工具。

Basalt 是一种基于约束设计图形的方法。 Basalt 的模型允许设计人员根据对象之间的关系进行思考,并且可以轻松构建和重用抽象。

Basalt仍在进行中。 如果你有兴趣了解更新,请单击此处。


原文链接:基于约束的图形设计 — BimAnt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/52569.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计Django二次元信息分享平台的设计及实现

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,我…

短视频不知道怎么定位?教你三个自我商业定位的方法,收藏学习

上一篇内容是我在我赢助手小禾呈序上讲了哪几类产品更适合私域变现,当然我相信有很多做抖音但没想好怎么变现的对吧? 如果说你还停留在我也不知道我可以靠什么赚钱这样的一个状态当中。那我给你三个自我商业定位的方法。 第一个方法,从工作上…

虹科Pico汽车示波器学院 | 第二课直播精彩回顾

直播精彩回顾(11.19) 第二课主题:《为什么使用示波器,可加速技师的技术水平提升?》 11月19日,虹科Pico汽车示波器学院第二课成功开课。第二课中,戈老师向学员们讲解了: 汽车示波器…

【网安神器篇】——LaZagne凭证收集工具

作者名:Demo不是emo 主页面链接:主页传送门 创作初心:舞台再大,你不上台,永远是观众,没人会关心你努不努力,摔的痛不痛,他们只会看你最后站在什么位置,然后羡慕或鄙夷座…

144.二叉树的前序遍历 递归 | 94.二叉树的中序遍历 递归 |145.二叉树的后序遍历 递归

144.二叉树的前序遍历 题目 给你二叉树的根节点 root ,返回它节点值的 前序 遍历。 输入:root [1,null,2,3] 输出:[1,2,3]示例 2: 输入:root [] 输出:[]示例 3: 输入:root …

11月动态|通过PWmat计算的离子浓度自由能相关文献发表在JCTC

11月 11月,龙讯旷腾完成Q-Flow和Q-Studio新版本的升级,完成了40余项功能的更新和上线;签约并行科技在高性能计算领域再下一城;汪林望博士受海河实验室邀请作线上主题报告;通过PWmat计算的离子浓度自由能相关文献发表在…

Unity笔记(15):OnTriggerEnter2D [2D]

1、给玩家标签设为Player 2、给碰撞的物体增加碰撞盒,并勾选isTrigger 3、编写脚本挂载到物体上 实现碰撞后物体会消失。 using System.Collections; using System.Collections.Generic; using UnityEngine;public class luobo : MonoBehaviour {private void OnT…

LeetCode-50-Pow(x, n)

1、递归 我们最简单的思路就是使用递归,每次就让x乘上Pow(x, n-1)的值。但是这样做的缺点在于递归时间过长会导致超时,因此我们可以使用快速幂进行优化。 快速幂的思想在于我们在求x的N次幂时,不使用x∗xN−1x*x^{N-1}x∗xN−1,…

访问工具--

下载地址: Releases Fndroid/clash_for_windows_pkg GitHub https://github.com/Fndroid/clash_for_windows_pkg/releases 安装好clash后,可以通过订阅链接或者导入yaml文件使用: 1、订阅链接 2、导入yaml文件 报错排查 你可能会遇到报错could not switch to this…

硬件学习路线调研

学习路线 《Verilog传奇》、《Verilog HDL高级数字设计》或者是《用于逻辑综合的VHDL》。不看书也能写出个三段式状态机就可以进入下一阶段了。 此外,你手上必须准备Verilog或者VHDL的官方文档,《verilog_IEEE官方标准手册-2005_IEEE_P1364》、《IEEE …

Hive分区表数据压缩

Hive分区表数据压缩 1.背景 目前公司的Hive分区表采用的TextFile格式存储,占用的存储空间较大,考虑到存储成本,需要对存储的历史数据进行压缩。 2.压缩格式选择 2.1 snappy压缩 优点:高速压缩速度和合理的压缩率;…

java - 数据结构,顺序表

1、顺序表和链表都属于数据结构的一部分。 2、数据结构:C的数据结构和JAVA的数据结构有什么不一样啊? 数据结构只是一个单独的学科,和语言没有关系。 用不同的语言实现一样的逻辑。 一、线性表 线性表(linear list)是n个具有相同特性的数据…

如何使用远程Linux虚拟机的图形界面

博客主页:https://tomcat.blog.csdn.net 博主昵称:农民工老王 主要领域:Java、Linux、K8S 期待大家的关注💖点赞👍收藏⭐留言💬 目录VMware Workstation ProSmarTTY在工作过程中,有时需要操作远…

微机----------LED显示接口

目录 LED显示器的工作原理采用专用芯片进行LED段译码软件译码法静态显示与动态显示LED显示器的工作原理 LED显示器的主要部分是七段发光管,这七段发光段分别称为a、b、c、d、e、f、g有的产品还附带有一个小数点DP。通过7个发光段的组合,可以显示0 ~ 9 和 A ~ F共16个字母数字…

果然AIGC还是对动漫制作下手了,不过是从数据集AnimeRun开始

原文链接:https://www.techbeat.net/article-info?id4327 作者:seven_ 最近AIGC领域的新工作几乎呈现一种井喷式的发展,借助AI模型天马行空的想象力,研究者们开始在各种图像和视频内容领域发力,本文介绍一篇发表在Neu…

MybatisPlus 处理保存实体对象时,对于枚举类型的数据库存储问题

MybatisPlus 处理保存实体对象时,对于枚举类型的数据库存储问题1. 前言1.1 先看问题代码1.2 存在的问题2. 解决前言问题2.1 自定义枚举2.2 附源码:3. 参考4. 推荐 Mybatis、MybatisPlus 其他相关问题的文章1. 前言 1.1 先看问题代码 如下:枚…

告别人工叫号!门诊排队叫号系统,这样配置,性价比高

很多人认为,那些大医院的叫号系统,确实既高效便捷、又能展现门诊综合服务实力。 但安装配置较为复杂,内部软件与硬件对接存在难度,价格也相对昂贵,对部分医院来讲,预算稍有不足,怎么办&#xff…

serverless-OpenWhisk安装

1.安装 默认我们已经有了一个k8s集群,采用helm方式安装。以下操作均在 Master 节点执行。 helm要求Helm v3.2.0或以上版本。 多节点worker打标签 如果要将OpenWhisk部署到具有多个工作节点的群集,我们建议使用节点关联将用于OpenWhisk控制平面的计算节点…

【论文阅读笔记】Pyramid Real Image Denoising Network

论文简介 本文是19年的论文,网络名为PRIDNet。代码地址为https://github.com/491506870/PRIDNet。在1080ti上,PRIDNet处理512x512图像需要大约50ms; 尽管深度卷积神经网络在特定噪声和去噪方面展示出非凡能力,但对于真实世界的噪声…

最好的天线基础知识!超实用 随时查询

天线作为无线电的发射和接收设备是影响信号强度和质量的重要设备,其在移动通信领域的重要性非常关键。通过对天线选型,天线安装,天线调整从而保障基站覆盖区域的信号强度与质量。对其的 掌握程度是网规与网优工程师的技能基本要求之一。下文重点说明天线要掌握哪些方面及其原理…