体素空间上的正则表达式

发布于 2024-12-06 03:11:28 字数 222 浏览 1 评论 0原文

有没有一种方法可以松散地描述 3d 体素网格中的对象(例如,通过模式匹配有限自动机),就像我们可以使用正则表达式松散地描述一维字符串中的模式一样?

假设我想描述一个“A”型体素的长方体,其下表面由“B”或“C”型体素组成,高度为 3,宽度为 5,并将此描述与体素字段相匹配以查找模式示例。我可以搜索精确模型(有点像 3D 中的 Boyer-Moore),但我需要为某些对象指定可变尺寸(例如上述长方体的可变长度)。

Is there a way to loosely describe an object (via pattern matching finite automata, for example) in 3d voxel grid in the same way we can loosely describe patterns in one-dimensional string with regexp?

Let's say I want to describe a cuboid of "A" type voxels with lower facet composed of "B" or "C" type voxels with height 3 and width 5, and match this description to voxel field to find examples of pattern. I can do some search for exact models (kind-of-like-Boyer-Moore-in-3D) but I need to specify variable dimensions for some objects (like variable length for aforementioned cuboid).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

给我一枪 2024-12-13 03:11:28

正则表达式是表达有限(并且仍然无限)语言集语法的紧凑方式。使用正则表达式,您不需要告诉在哪里寻找下一个符号,因为众所周知您正在处理一个字符串并迭代其字符,将它们作为语言的符号......但在 3D 中您将需要告诉走哪条路。

您可以将其视为一台 3D 图灵机,即一台具有内部状态并且可以从 3D“磁带”读取符号的图灵机,因为我们只是验证,让我们忽略对磁带的写入。然后,该图灵机将在 3D“磁带”(又名 3D 体素网格)上行走,并将体素读取为符号,读取每个符号后,图灵机的内部状态将根据一定的规律发生变化。执行结束后,机器的最终状态会告诉您是否匹配。现在,冯·纽曼架构中的这些定律是将磁带中的数据解释为指令,但我们需要哈佛架构,即指令与数据分离。现在您想要的是一种描述图灵机指令的方法。 [您可以将其视为 Logo 中的乌龟,但是是 3D 形式]。

遵循正则表达式的精神,我们更喜欢一种类似于实际结构的语言。如果我们使其基于文本,它将是一种描述性语言(因为命令式语言并不比您最喜欢的图灵完整语言更好),它必须说例如(用英语):

There is a voxel type A and then moving (x1, y1, z1) from that there is a voxel of type B or C and then moving (x2, y2, z3) from that there is a voxel type D

这描述了图灵机正在寻找什么,使用测试所有潜在匹配的回溯算法,它将按预期工作。

请注意,我不知道体素的可能值集。也就是说,我不认识字母。所以我刚刚说了类型 A、类型 B、类型 C 和类型 D 作为示例,其中之一可能是无体素的表示,其他可能是颜色或您正在使用的任何内容。根据需要可以有多种类型的体素。如果体素的类型很复杂,则必须将其描述插入其中。

我一直在考虑这种语言的实际使用,并且很快出现的一个问题是旋转,我必须决定 X 轴上的三个 A 型体素被认为与 Z 轴上的三个 A 型体素相同,更好的是允许用语言来描述它。

现在,如果体素是节点,则描述路径非常相似,我已经编写了一种语言来描述 2D 路径作为私有项目的一部分(将它们存储在数据库中,想想看......),这非常简单,它为每个方向保留一个字符并使用数字表示步数,例如:“2d5l1u”。对 3D 进行同样的操作并添加分组和匹配的方式即可。为了解决旋转问题,有必要扩展方向以允许析取来表达匹配的替代配置。在我想到的一些关于它如何工作的示例中,这将变得更加清晰(我没有在 EBNF 或类似的形式中使用过正式语法):

在 X 轴上匹配 A 型三个体素的线:

(A1X){3}

这里我插入匹配“A”移动“1X”,用括号“(”和“)”进行分组,用大括号“{”和“}”进行量化。这展开如下:

A1XA1XA1X

最后一个“1X”不会影响结果,所以它也可能是:

A1XA1XA

它清楚地说:匹配 A 型体素,在 X 上移动 1 并匹配 A 型体素,在 X 上移动 1 X 并匹配 A 型体素。

在 X 轴或 Z 轴上匹配 A 型三个体素的线:

(A1X){3}|(A1Z){3}

替代方案:

(A1[X|Z]){3}

这里我使用括号“[”和“]”来创建一个“类”,它的位置告诉它是关于方向的,并且它只是包括可能的轴,不要混淆:

[(A1X)|(A1Z)]{3}

这将匹配三个 A 型体素,但它们可能不在同一轴上,它们只需连续并与其邻居共享 X 轴或 Z 轴。

在平面 X、Y 上匹配一组 3x3 体素类型 a:

(((A1X){3})1Y){3}

这会匹配 X 轴上的一条线,并在 Y 轴上移动 1 以匹配另一条线,依此类推。这意味着在对重复“([(A1X)]{16})”进行分组后,我们回溯到比赛开始执行以下移动“1Y”的位置。展开它的方法是:

(A1XA1XA1X)1Y(A1XA1XA1X)1Y(A1XA1XA1X)1Y

查看剩下的括号,这些意味着回溯到比赛开始的地方。因此,程序将检查组内的内容,完成后它将返回进入组之前的位置,并在进入组后继续执行。

匹配由忽略类型的体素(在任何轴上)分隔的一对 A 型体素:

A1(X|Y|Z).1(X|Y|Z)A1(X|Y|Z)

受正则表达式的影响,我们使用点“.”。表示任何类型的体素。

我仍然不确定使用负值是否比在其他轴上使用其他字母更好,而且我认为数字 1 可以是可选的。还有正则表达式语法的其他部分,例如“+”、“*”和“?”必须更仔细地考虑。在证明不存在歧义之前,最好对任何量化强制执行“{”和“}”。

正如您可能已经注意到的那样,添加另一个运动方向或完全另一个轴不会有问题,因此这个端口很好地表示四个维度,如:

(A1[X|Y|Z|W]){3}

使用点“”也可能很好。表示任何方向:

(A1.){3}

在未指定的情况下假设任何方向存在一个问题,即该语言被定义为识别什么是方向并根据表达式内部的位置将它们与体素类型区分开。所以“(A1B1){3}”不会映射到“(A1.B1.){3}”,因为它会以“B”作为移动方向,可以通过尾随数字推断出含义结局,但不知道是否能明确。

最后,这将匹配由 A 型体素组成的平面 X、Y 中的任何有效俄罗斯方块:

(A1[X|Y]){4}

如果我们假设世界只是二维的并且我们允许忽略数字一,那么它会简化为:

(A.){4}

我很高兴那。尽管如此,对于复杂的结构,您应该考虑使用更复杂、不太紧凑且更易读的表示法。

这就是我将正则表达式推广到二维、三维或更多维的理论。

编辑:

如果体素的类型很复杂或引起歧义,我建议用尖括号“<”来编写它和“>”,例如您可以使用原始体素数据的十六进制值:

(<0088FF>.){4}

Regular expressions are a compact way to express the syntax of a limited (and still infinite) set of languages. With regular expressions you don't need to tell where to look for the next symbol, since it is known that you are working on a string and iterating over its characters taking them as the symbols of the language... but in 3D you will need to tell what way to go.

You can think about it as a 3D Turing machine, that is a Turing machine that has an internal state and can read symbols from a 3D "tape", since we are only verifying let's ignore writing to the tape. Then, this Turing machine will walk the 3D "tape" aka the 3D voxel grid and read voxels as symbols, after reading each symbol the internal state of the Turing machine will change according to certain laws. Once the execution is over the final state of the machine tell you if it were a match or not. Now these laws in a Von Newman Architecture are an interpretation of the data from tape as instruction, but we want a Harvard architecture, that is that the instructions are separated from the data. Now what you want is a way to describe those instructions for the Turing machine. [You can think of this as the turtle of Logo but in 3D].

Following the spirit of the regular expressions we would prefer a language that resembles the actual structure. If we make it text based it will be a descriptive language (because an imperative one is no better than your favorite Turing complete one), it will have to say for example (in English):

There is a voxel type A and then moving (x1, y1, z1) from that there is a voxel of type B or C and then moving (x2, y2, z3) from that there is a voxel type D

This describes what the Turing machine is looking for, with a backtracking algorithm that test all potential matches it will work as expected.

Please note that I don't know the set of possible values of the voxels. That is, I don’t know the alphabet. So I've just said type A, type B, type C and type D as examples, one of those may be the representation of no voxel, and the others may be colors or whatever you are using. There can be as many types of voxels as needed. If the type of the voxel is complex the description of it got to be inserted there.

I've been thinking of practical use this kind of language and one problem that arises very quickly is rotations, I have to decide that three voxels type A over the X axis is considered the same a three voxels type A over the Z axis, the better is to allow to describe that in the language.

Now it is very similar to describe a path if the voxels are nodes, I've done a language to describe 2D paths as part of a private project (to store them in a database, go figure...), it is very simple, it reserve a character for every direction and uses a number for the steps, for example: "2d5l1u". Doing the same for 3D and adding a way to group and match will do. To solve the rotation problem it will be necessary to expand the direction to allow disjunctions to express alternative configurations for the match. This will become clearer on some example of how it may work that I've thought of (I've not worked a formal syntax in EBNF or similar):

Matching a line of three voxels type A over the X axis:

(A1X){3}

Here I intercalate matching "A" with movement "1X", use parenthesis "(" and ")" for grouping and the curly brackets "{" and "}" to quantify. This unrolls to this:

A1XA1XA1X

The last "1X" doesn't affect the result, so it may as well be:

A1XA1XA

And it clearly says: Match a type A voxel, move 1 over the X and match a type A voxel, move 1 over the X and match a type A voxel.

Matching a line of three voxels type A over the X axis or the Z axis:

(A1X){3}|(A1Z){3}

Alternative:

(A1[X|Z]){3}

Here I use brackets "[" and "]" to make a 'class', the location of it tells it is about the direction and it only includes the possible axis, do not confuse with:

[(A1X)|(A1Z)]{3}

This will match three voxels type A but they may not be on the same axis, they only got to be contiguous and share either the X axis or the Z axis with it neighbor.

Matching a 3x3 set of voxels type a over the plane X, Y:

(((A1X){3})1Y){3}

This matches a line over the X axis and the moves 1 over the Y axis to match another and so on. It implies that after grouping a repetition "([(A1X)]{16})" we backtrack to where the match begun to execute the following move "1Y". To unroll it would be:

(A1XA1XA1X)1Y(A1XA1XA1X)1Y(A1XA1XA1X)1Y

Look the remaining parenthesis, those means to backtrack to where the match begun. So the program will check what is inside of the group and when it is done it will go back where it was before entering the group and continue executing after it.

Matching a pair of voxels type A separated by a voxel of ignored type (over any axis):

A1(X|Y|Z).1(X|Y|Z)A1(X|Y|Z)

Influenced by regular expressions we use the dot "." to represent any type of voxel.

I still don't decide if it is better to use negative values than to use other letters for other axis, also I consider that the number 1 could be optional. Also other parts of the syntax of regular expressions such as "+", "*", and "?" got to be though out more carefully. It may be good to enforce "{" and "}" for any quantification until proven that there is no ambiguity.

As you may have notice it will not be a problem to add another direction of movement or entirely another axis, so this port very well to say four dimensions, as in:

(A1[X|Y|Z|W]){3}

It may also be good to use the dot "." to represent any direction:

(A1.){3}

There is a problem with assuming any direction when not specified and that is that this language is defined to identify what is a direction and distinguish them from voxel types based on the location inside of the expression. So "(A1B1){3}" will not map to "(A1.B1.){3}" because it will take "B" as the direction to move, it may be possible to infer the meaning by the trailing number at the end, but I don't know if it will be unambigous.

Lastly this will match any valid tetris piece in the plane X, Y made of voxels type A:

(A1[X|Y]){4}

If we assume that the world is only bidimensional and that we allow to ignore the number one, it reduces to this:

(A.){4}

And I'm happy with that. Nevertheless, you should consider a more complex, less compact and more readable notation for complex structures.

And that is my theory for generalizing regular expressions to two, three or more dimensions.

EDIT:

If the type of voxel is complex or causes ambiguity I propose to write it with angular brackets "<" and ">", so for example you can use the hex value of the raw voxel data:

(<0088FF>.){4}
猫卆 2024-12-13 03:11:28

我对 3D 或体素了解不多,但如果您可以使用标记将 3D 空间转换为一维表示,那么您可以在其上使用正则表达式。

简化示例:

对于具有蓝色面、红色面、绿色面和其他 3 个我们不关心的面的立方体:

<object>
    <cube>
        <faces>
            <face orientation="up" color="blue">
                <border neighborOrient="west">
                <border neighborOrient="south">
            <face orientation="west" color="red">
            <face orientation="south" color="green">
            ...
        </faces>
    </cube>
</object>

您的正则表达式可以在同一立方体中查找共享边框的面。正则表达式最适合文本,因此您的第一步应该是找到一种“扁平化”文本的方法。

I don't know much about 3D or voxels, but if you can transform your 3D space into a one-dimensional representation using a markup, then you can use a regex on it.

Simplified example:

For a cube with a blue face, red face, green face, and 3 others we don't care about:

<object>
    <cube>
        <faces>
            <face orientation="up" color="blue">
                <border neighborOrient="west">
                <border neighborOrient="south">
            <face orientation="west" color="red">
            <face orientation="south" color="green">
            ...
        </faces>
    </cube>
</object>

Your regex could look for faces within the same cube which share a border. Regexes work best with text, so your first step should be to find a way to "flatten" down to text.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文