कैसे Python में 3D सीन ग्राफ़ को ट्रैवर्स करें

कैसे Python में 3D सीन ग्राफ़ को ट्रैवर्स करें

Aspose.3D FOSS में सीन ग्राफ एक ट्री है Node ऑब्जेक्ट्स जिनका मूल scene.root_node. हर 3D फ़ाइल, चाहे वह OBJ, glTF, STL, COLLADA, या 3MF से लोड की गई हो, समान ट्री स्ट्रक्चर बनाती है। इसे ट्रैवर्स करना जानने से आप जियोमेट्री का निरीक्षण कर सकते हैं, पॉलीगॉन गिन सकते हैं, प्रकार के अनुसार ऑब्जेक्ट्स को फ़िल्टर कर सकते हैं, और जटिल सीन के विशिष्ट भागों को प्रोसेस कर सकते हैं।.

स्टेप बाय स्टेप गाइड

चरण 1: इंस्टॉल और इम्पोर्ट

PyPI से Aspose.3D FOSS इंस्टॉल करें:

pip install aspose-3d-foss

जिस क्लास की आपको आवश्यकता है उसे इम्पोर्ट करें:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

सभी सार्वजनिक क्लासें इस के अंतर्गत रहती हैं aspose.threed या इसके उप‑पैकेजों (aspose.threed.entities, aspose.threed.utilities).


चरण 2: फ़ाइल से सीन लोड करें

स्थैतिक का उपयोग करें Scene.from_file() मेथड का उपयोग करके किसी भी समर्थित फ़ॉर्मेट को खोलें। फ़ॉर्मेट फ़ाइल एक्सटेंशन से स्वचालित रूप से पता लगाया जाता है:

scene = Scene.from_file("model.gltf")

आप स्पष्ट लोड विकल्पों के साथ भी खोल सकते हैं:

from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions

options = ObjLoadOptions()
options.enable_materials = True

scene = Scene()
scene.open("model.obj", options)

लोड करने के बाद, scene.root_node ट्री की रूट है। सभी आयातित नोड्स इस नोड के बच्चे या वंशज हैं।.


चरण 3: एक रिकर्सिव ट्रैवर्सल फ़ंक्शन लिखें

सबसे सरल ट्रैवर्सल गहराई‑प्रथम क्रम में प्रत्येक नोड को विज़िट करता है:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

def traverse(node, depth=0):
    prefix = "  " * depth
    entity_name = type(node.entity).__name__ if node.entity else "-"
    print(f"{prefix}[{entity_name}] {node.name}")
    for child in node.child_nodes:
        traverse(child, depth + 1)

scene = Scene.from_file("model.gltf")
traverse(scene.root_node)

उदाहरण आउटपुट:

[-]
  [-] Armature
    [Mesh] Body
    [Mesh] Eyes
  [-] Ground
    [Mesh] Plane

<button class=“hextra-code-copy-btn hx-group/copybtn hx-transition-all active:hx-opacity-50 hx-bg-primary-700/5 hx-border hx-border-black/5 hx-text-gray-600 hover:hx-text-gray-900 hx-rounded-md hx-p-1.5 dark:hx-bg-primary-300/10 dark:hx-border-white/10 dark:hx-text-gray-400 dark:hover:hx-text-gray-50” title=“Copy code”

<div class="copy-icon group-[.copied]/copybtn:hx-hidden hx-pointer-events-none hx-h-4 hx-w-4"></div>
<div class="success-icon hx-hidden group-[.copied]/copybtn:hx-block hx-pointer-events-none hx-h-4 hx-w-4"></div>

नोट: रूट नोड का नाम खाली है (""), इसलिए पहली पंक्ति दिखाती है [-] बिना नाम के आगे।.

node.child_nodes इन्सर्शन क्रम में बच्चों को लौटाता है (वह क्रम जिसमें आयातकर्ता या उपयोगकर्ता ने उन्हें जोड़ा था)।.


चरण 4: प्रत्येक नोड पर एंटिटी प्रॉपर्टीज़ तक पहुँचें

उपयोग करें node.entity नोड से जुड़ी पहली एंटिटी प्राप्त करने के लिए, या node.entities सभी को इटररेट करने के लिए। फ़ॉर्मेट-विशिष्ट प्रॉपर्टीज़ तक पहुँचने से पहले प्रकार जाँचें:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

def print_entity_details(node, depth=0):
    indent = "  " * depth
    for entity in node.entities:
        if isinstance(entity, Mesh):
            mesh = entity
            print(f"{indent}Mesh '{node.name}':")
            print(f"{indent}  vertices  : {len(mesh.control_points)}")
            print(f"{indent}  polygons  : {mesh.polygon_count}")
            print(f"{indent}  cast_shadows   : {mesh.cast_shadows}")
            print(f"{indent}  receive_shadows: {mesh.receive_shadows}")
    for child in node.child_nodes:
        print_entity_details(child, depth + 1)

scene = Scene.from_file("model.gltf")
print_entity_details(scene.root_node)

node.transform.translation, node.transform.rotation, और node.transform.scaling स्थानीय-स्थान ट्रांसफ़ॉर्म देते हैं।. node.global_transform मूल्यांकित वर्ल्ड-स्पेस परिणाम देता है (के साथ global_transform.scale वर्ल्ड-स्पेस स्केल के लिए)।.


चरण 5: इकाई प्रकार के आधार पर नोड्स को फ़िल्टर करें

केवल विशिष्ट entity प्रकारों पर काम करने के लिए, एक जोड़ें isinstance ट्रैवर्सल के भीतर गार्ड:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

def find_mesh_nodes(node, results=None):
    if results is None:
        results = []
    for entity in node.entities:
        if isinstance(entity, Mesh):
            results.append(node)
            break   # One match per node is enough
    for child in node.child_nodes:
        find_mesh_nodes(child, results)
    return results

scene = Scene.from_file("model.gltf")
mesh_nodes = find_mesh_nodes(scene.root_node)
print(f"Found {len(mesh_nodes)} mesh node(s)")
for n in mesh_nodes:
    print(f"  {n.name}")

यह पैटर्न बड़े पैमाने पर संचालन के लिए उपयोगी है: प्रत्येक मेष नोड पर ट्रांसफ़ॉर्म लागू करना, सामग्री बदलना, या सब‑ट्रीज़ को निर्यात करना।.


चरण 6: सभी मेष एकत्र करें और वर्टेक्स गिनती प्रिंट करें

एक ही पास में मेष आँकड़े एकत्रित करें:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

def collect_meshes(node, results=None):
    if results is None:
        results = []
    if isinstance(node.entity, Mesh):
        results.append((node.name, node.entity))
    for child in node.child_nodes:
        collect_meshes(child, results)
    return results

scene = Scene.from_file("model.gltf")
meshes = collect_meshes(scene.root_node)

print(f"Total meshes: {len(meshes)}")
total_verts = 0
total_polys = 0

for name, mesh in meshes:
    verts = len(mesh.control_points)
    polys = mesh.polygon_count
    total_verts += verts
    total_polys += polys
    print(f"  {name}: {verts} vertices, {polys} polygons")

print(f"Scene totals: {total_verts} vertices, {total_polys} polygons")

सामान्य समस्याएँ

समस्यासमाधान
AttributeError: 'NoneType' object has no attribute 'polygons'के साथ गार्ड if node.entity is not None या isinstance(node.entity, Mesh) मेश प्रॉपर्टीज़ तक पहुँचने से पहले। एंटिटीज़ के बिना नोड्स वापस लौटाते हैं None.
ट्रैवर्सल जल्दी रुक जाता हैसुनिश्चित करें कि पुनरावृत्ति तक पहुँचती है node.child_nodes. यदि आप केवल इटररेट करते हैं scene.root_node.child_nodes (पुनरावर्ती रूप से नहीं), आप सभी वंशजों को चूक जाते हैं।.
संकलित परिणामों में Mesh गायब हैजाँचें कि फ़ाइल फ़ॉर्मेट पदानुक्रम को संरक्षित रखता है। OBJ सभी ज्यामिति को एकल नोड स्तर में फ्लैट कर देता है। गहरी पदानुक्रमों के लिए glTF या COLLADA का उपयोग करें।.
node.entity केवल पहली entity लौटाता हैउपयोग करें node.entities (the full list) जब कोई नोड कई इकाइयाँ ले जाता है।. node.entity का संक्षिप्त रूप है node.entities[0] जब entities खाली नहीं है।.
collect_meshes लोड किए गए STL के लिए 0 परिणाम लौटाता हैSTL फ़ाइलें आमतौर पर एक एकल फ्लैट नोड बनाती हैं, जिसमें एक mesh entity सीधे नीचे होता है। root_node. जाँचें root_node.child_nodes[0].entity सीधे।.
नोड नाम खाली स्ट्रिंग हैंकुछ फ़ॉर्मेट (बाइनरी STL, कुछ OBJ फ़ाइलें) ऑब्जेक्ट नाम संग्रहीत नहीं करते। नोड्स के पास खाली name स्ट्रिंग्स; पहचान के लिए इंडेक्स का उपयोग करें।.

अक्सर पूछे जाने वाले प्रश्न

एक सीन ग्राफ कितनी गहराई तक हो सकता है?

कोई कठोर सीमा नहीं है। Python की डिफ़ॉल्ट पुनरावृत्ति सीमा (1000 फ्रेम) पुनरावर्ती ट्रैवर्सल फ़ंक्शनों पर लागू होती है। बहुत गहरी पदानुक्रमों के लिए, पुनरावृत्ति को एक स्पष्ट स्टैक में बदलें:

from collections import deque
from aspose.threed import Scene

scene = Scene.from_file("deep.gltf")
queue = deque([(scene.root_node, 0)])

while queue:
    node, depth = queue.popleft()
    print("  " * depth + node.name)
    for child in node.child_nodes:
        queue.append((child, depth + 1))

क्या मैं ट्रैवर्सल के दौरान ट्री को संशोधित कर सकता हूँ?

नोड्स को … से जोड़ें या हटाएँ नहीं child_nodes इसे इटररेट करते समय। संशोधित करने के लिए नोड्स को पहले पास में एकत्र करें, फिर दूसरे पास में परिवर्तन लागू करें।.

मैं नाम द्वारा एक विशिष्ट नोड कैसे खोजूँ?

उपयोग करें node.get_child(name) नाम द्वारा सीधे बच्चे को खोजने के लिए। गहरी खोज के लिए, नाम फ़िल्टर के साथ ट्री को ट्रैवर्स करें:

def find_by_name(root, name):
    if root.name == name:
        return root
    for child in root.child_nodes:
        result = find_by_name(child, name)
        if result:
            return result
    return None

target = find_by_name(scene.root_node, "Wheel_FL")

क्या node.entity हमेशा एक Mesh लौटाता है?

नहीं। एक नोड किसी भी एंटिटी प्रकार को रख सकता है: Mesh, Camera, Light, या कस्टम एंटिटीज़। हमेशा जांचें isinstance(node.entity, Mesh) mesh-विशिष्ट प्रॉपर्टीज़ का उपयोग करने से पहले।.

मैं नोड की विश्व-स्थान स्थिति कैसे प्राप्त करूँ?

पढ़ें node.global_transform.translation. यह विश्व स्थान में मूल्यांकित स्थिति है, सभी पूर्वज रूपांतरणों को ध्यान में रखते हुए। यह केवल‑पढ़ने योग्य है; संशोधित करें node.transform.translation नोड को पुनःस्थापित करने के लिए।.

क्या मैं सीन में कुल पॉलीगॉन की संख्या बिना ट्रैवर्सल लिखे गिन सकता हूँ?

API के माध्यम से सीधे नहीं; कोई scene.total_polygon_count गुणधर्म। उपयोग करें collect_meshes और जोड़ें mesh.polygon_count परिणामों में, जैसा कि चरण 6 में दिखाया गया है।.

 हिन्दी