亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

由角點定義的邊界框對象的嵌套屬性

由角點定義的邊界框對象的嵌套屬性

慕森王 2023-09-12 17:20:22
通常,攪拌器腳本必須從 3D 點集合計算包圍邊界框,例如將默認攪拌器立方體邊界框作為輸入,coords = np.array(     [[-1.  1. -1.],      [-1.  1.  1.],      [ 1. -1. -1.],      [ 1. -1.  1.],      [ 1.  1. -1.],      [ 1.  1.  1.]] )bfl = coords.min(axis=0)tbr = coords.max(axis=0)G  = np.array((bfl, tbr)).Tbbox_coords = [i for i in itertools.product(*G)]例如,邊界框坐標將是相同順序的立方體坐標尋找一些Python“迭代魔法”,使用上面的和("left", "right"), ("front", "back"),("top", "bottom"),來制作一個輔助類>>> bbox = BBox(bfl, tbr)>>> bbox.bottom.front.left(-1, -1, -1)>>> bbox.top.front(0, -1, 1)>> bbox.bottom(0, 0, -1)即角頂點、邊的中心、矩形的中心。(1、2 或 4 個角的平均總和)在攪拌機中,頂部為 +Z,前面為 -Y。最初是在考慮用靜態計算值填充嵌套字典之類的東西d = {    "front" : {        "co" : (0, -1, 0),        "top" : {            "co" : (0, -1, 1),            "left" : {"co" : (-1, -1, 1)},            }        }       }通常,攪拌器腳本必須從 3D 點集合計算包圍邊界框,例如將默認攪拌器立方體邊界框作為輸入,coords = np.array(     [[-1.  1. -1.],      [-1.  1.  1.],      [ 1. -1. -1.],      [ 1. -1.  1.],      [ 1.  1. -1.],      [ 1.  1.  1.]] )bfl = coords.min(axis=0)tbr = coords.max(axis=0)G  = np.array((bfl, tbr)).Tbbox_coords = [i for i in itertools.product(*G)]例如,邊界框坐標將是相同順序的立方體坐標尋找一些Python“迭代魔法”,使用上面的和("left", "right"), ("front", "back"),("top", "bottom"),來制作一個輔助類>>> bbox = BBox(bfl, tbr)>>> bbox.bottom.front.left(-1, -1, -1)>>> bbox.top.front(0, -1, 1)>> bbox.bottom(0, 0, -1)即角頂點、邊的中心、矩形的中心。(1、2 或 4 個角的平均總和)在攪拌機中,頂部為 +Z,前面為 -Y。最初是在考慮用靜態計算值填充嵌套字典之類的東西d = {    "front" : {        "co" : (0, -1, 0),        "top" : {            "co" : (0, -1, 1),            "left" : {"co" : (-1, -1, 1)},            }        }       }
查看完整描述

3 回答

?
牧羊人nacy

TA貢獻1862條經驗 獲得超7個贊

這是兩個相似的版本。兩者的想法都是,您始終返回一個BBox對象,并且僅更改一個變量x ,該變量指示您通過left, , ... 指定的尺寸。最后,您有一個用于計算剩余角的中心的right函數。x


第一種方法使用函數,因此您必須調用它們bbox.bottom().front().left().c()。這里的主要區別在于并非所有組合


top

top left

top right

top left front

...

在創建對象時計算,但僅在調用它們時計算。



import numpy as np

import itertools


class BBox:

    """

    ("left", "right"), -x, +x

    ("front", "back"), -y, +y

    ("bottom", "top"), -z, +z

    """

    def __init__(self, bfl, tbr):

        self.bfl = bfl

        self.tbr = tbr


        self.g = np.array((bfl, tbr)).T


        self.x = [[0, 1], [0, 1], [0, 1]]


    def c(self):  # get center coordinates

        return np.mean([i for i in itertools.product(*[self.g[i][self.x[i]] for i in range(3)])], axis=0)


    def part(self, i, xi):

        assert len(self.x[i]) == 2

        b2 = BBox(bfl=self.bfl, tbr=self.tbr)

        b2.x = self.x.copy()

        b2.x[i] = [xi]

        return b2


    def left(self):

        return self.part(i=0, xi=0)


    def right(self):

        return self.part(i=0, xi=1)


    def front(self):

        return self.part(i=1, xi=0)


    def back(self):

        return self.part(i=1, xi=1)


    def bottom(self):

        return self.part(i=2, xi=0)


    def top(self):

        return self.part(i=2, xi=1)



bbox = BBox(bfl=[-1, -1, -1], tbr=[1, 1, 1])

>>> bbox.bottom().front().left().c()

(-1, -1, -1)


>>> bbox.top().front().c()

(0, -1, 1)


>>> bbox.bottom().c()

(0, 0, -1)

第二種方法使用本身就是BBox對象的屬性。當您取消注釋函數中的 print 語句時,init您可以了解構造過程中發生的所有遞歸調用。因此,雖然查看這里發生的情況可能會更復雜,但訪問屬性時會更方便。


class BBox:

    def __init__(self, bfl, tbr, x=None):

        self.bfl = bfl

        self.tbr = tbr

        self.g = np.array((bfl, tbr)).T


        self.x = [[0, 1], [0, 1], [0, 1]] if x is None else x

        

        # print(self.x)  # Debugging 

        self.left = self.part(i=0, xi=0)

        self.right = self.part(i=0, xi=1)

        self.front = self.part(i=1, xi=0)

        self.back = self.part(i=1, xi=1)

        self.bottom = self.part(i=2, xi=0)

        self.top = self.part(i=2, xi=1)


    def c(self):  # get center coordinates

        return np.mean([i for i in itertools.product(*[self.g[i][self.x[i]] 

                        for i in range(3)])], axis=0)


    def part(self, i, xi):

        if len(self.x[i]) < 2:

            return None

        x2 = self.x.copy()

        x2[i] = [xi]

        return BBox(bfl=self.bfl, tbr=self.tbr, x=x2)


bbox = BBox(bfl=[-1, -1, -1], tbr=[1, 1, 1])

>>> bbox.bottom.front.left.c()

(-1, -1, -1)

您還可以在構造函數的末尾添加類似的內容,以刪除無效的屬性。(以防止類似的事情bbox.right.left.c())。它們None以前是,但AttributeError可能更合適。


   def __init__(self, bfl, tbr, x=None):

       ...

       for name in ['left', 'right', 'front', 'back', 'bottom', 'top']:

           if getattr(self, name) is None:

               delattr(self, name)

你也可以添加一個__repr__()方法:


    def __repr__(self):

        return repr(self.get_vertices())


    def get_vertices(self):

        return [i for i in itertools.product(*[self.g[i][self.x[i]]

                                               for i in range(3)])]


    def c(self):  # get center coordinates

        return np.mean(self.get_vertices(), axis=0)



bbox.left.front

# [(-1, -1, -1), (-1, -1, 1)]

bbox.left.front.c()

# array([-1., -1.,  0.])

編輯

一段時間后回到這個問題后,我認為最好只添加相關屬性而不添加全部,然后刪除其中一半。所以我能想到的最緊湊/最方便的類是:


class BBox:

    def __init__(self, bfl, tbr, x=None):

        self.bfl, self.tbr = bfl, tbr

        self.g = np.array((bfl, tbr)).T

        self.x = [[0, 1], [0, 1], [0, 1]] if x is None else x


        for j, name in enumerate(['left', 'right', 'front', 'back', 'bottom', 'top']):

            temp = self.part(i=j//2, xi=j%2)

            if temp is not None:

                setattr(self, name, temp)


    def c(self):  # get center coordinates

        return np.mean([x for x in itertools.product(*[self.g[i][self.x[i]]

                                                       for i in range(3)])], axis=0)


    def part(self, i, xi):

        if len(self.x[i]) == 2:

            x2, x2[i] = self.x.copy(), [xi]

            return BBox(bfl=self.bfl, tbr=self.tbr, x=x2)


查看完整回答
反對 回復 2023-09-12
?
一只斗牛犬

TA貢獻1784條經驗 獲得超2個贊

這是使用迭代方法創建字典的另一個解決方案:


import numpy 

import itertools


directions = ['left', 'right', 'front', 'back', 'bottom', 'top']

dims = np.array([  0,       0,       1,      1,        2,     2])  # xyz


def get_vertices(bfl, tbr, x):

    g = np.array((bfl, tbr)).T

    return [v for v in itertools.product(*[g[ii][x[ii]] for ii in range(3)])]



bfl = [-1, -1, -1]

tbr = [1, 1, 1]


d = {}

for i in range(6):

    x = [[0, 1], [0, 1], [0, 1]]

    x[i//2] = [i % 2]  # x[dim[i] = min or max  

    d_i = dict(c=np.mean(get_vertices(bfl=bfl, tbr=tbr, x=x), axis=0))


    for j in np.nonzero(dims != dims[i])[0]:

        x[j//2] = [j % 2]

        d_ij = dict(c=np.mean(get_vertices(bfl=bfl, tbr=tbr, x=x), axis=0))


        for k in np.nonzero(np.logical_and(dims != dims[i], dims != dims[j]))[0]:

            x[k//2] = [k % 2]


            d_ij[directions[k]] = dict(c=np.mean(get_vertices(bfl=bfl, tbr=tbr, x=x), axis=0))

        d_i[directions[j]] = d_ij

    d[directions[i]] = d_i



d

# {'left': {'c': array([-1.,  0.,  0.]),

#    'front': {'c': array([-1., -1.,  0.]),

#      'bottom': {'c': array([-1., -1., -1.])},

#      'top': {'c': array([-1., -1.,  1.])}},

#    'back': {'c': array([-1.,  1.,  1.]),

#      'bottom': {'c': array([-1.,  1., -1.])},

#      'top': {'c': array([-1.,  1.,  1.])}}, 

#   ....

您可以將其與鏈接的問題結合起來,通過 訪問字典的鍵d.key1.key2。


查看完整回答
反對 回復 2023-09-12
?
小怪獸愛吃肉

TA貢獻1852條經驗 獲得超1個贊

我到了哪里了。


以某種方式添加了這個作為答案,以更好地解釋我的問題


循環遍歷立方體的 8 個頂點,將 3 個名稱與每個有效角相匹配。


“swizzle”是構成角的三個軸方向的排列。


直接輸入自嵌套字典d[i][j][k] = value是創建它們的一種輕松方式。(pprint(d)下)


高興的是,從那里開始,它變得丑陋,一些鴨子打字從簡單的 8 垂直真值表中獲取元素索引。


沒有特殊原因,將返回生成類的方法作為包裝器,但我沒有這樣使用它。


import numpy as np

import pprint

import operator

from itertools import product, permutations

from functools import reduce

from collections import defaultdict



class NestedDefaultDict(defaultdict):

    def __init__(self, *args, **kwargs):

        super(NestedDefaultDict, self).__init__(NestedDefaultDict, *args, **kwargs)


    def __repr__(self):

        return repr(dict(self))



def set_by_path(root, items, value):

    reduce(operator.getitem, items[:-1], root)[items[-1]] = value



def create_bbox_swizzle(cls, dirx=("left", "right"), diry=("front", "back"), dirz=("bottom", "top")):

    d = NestedDefaultDict()

    data = {}

    for i, cnr in enumerate(product(*(dirx, diry, dirz))):

        vert = {"index": i}

        data[frozenset(cnr)] = i

        for perm in permutations(cnr, 3):

            set_by_path(d, perm, vert)

    pprint.pprint(d)


    def wire_up(names, d):

        class Mbox:

            @property

            def co(self):

                return self.coords[self.vertices].mean(axis=0)

            def __init__(self, coords):

                self.coords = np.array(coords)

                self.vertices = [v for k, v in data.items() if k.issuperset(names)]

                pass


            def __repr__(self):

                if len(names) == 1:

                    return f"<BBFace {self.vertices}/>"

                elif len(names) == 2:

                    return f"<BBEdge {self.vertices}/>"

                elif len(names) == 3:

                    return f"<BBVert {self.vertices}/>"

                return "<BBox/>"

            pass


        def f(k, v):

            def g(self):

                return wire_up(names + [k], v)(self.coords)

            return property(g)


        for k, v in d.items():

            if isinstance(v, dict):

                setattr(Mbox, k, (f(k, v)))

            else:

                setattr(Mbox, k, v)

        return Mbox

    return wire_up([], d)



@create_bbox_swizzle

class BBox:

    def __init__(self, *coords, **kwargs):

        pass

試駕:


>>> bbox = BBox(coords)  # used coords instead of corners

>>> bbox.co

array([ 5.96046448e-08, -1.19209290e-07,  0.00000000e+00])


>>> bbox.left.bottom

<BBEdge [0, 2]/>


>>> bbox.left.bottom.vertices

[0, 2]


>>> bbox.left.bottom.co

array([-1.00000036e+00, -1.19209290e-07,  0.00000000e+00])


查看完整回答
反對 回復 2023-09-12
  • 3 回答
  • 0 關注
  • 151 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號