I received assistance here on how to find shapes using attribute values in a Python script.
Since it was inconvenient to directly input attribute values into the code each time, I tried entering them through the Python console, but it was impossible.
Then, I found a way to implement a GUI using Jython and tried it.
It's currently working well, including searches for Korean(2Bytes char) attributes. While it may not be the most elegant solution, I hope it helps others.
("Functional limitation - Search does not work when the attribute value is a number.")
As a program designed to handle large datasets, CityEngine must include a core functionality to search for shapes based on their attributes.(Does this feature really exist, or am I missing something?)
# Last modified: 2024-08-29 19:00:00 KST
# Version: 1.4
# Requirement: Fix the issue where the input GUI window was not displaying correctly.
'''
@author: desert
'''
from scripting import *
from javax.swing import JFrame, JLabel, JTextField, JButton, JPanel
from java.awt import GridLayout, BorderLayout
from java.awt.event import ActionListener
# Get a CityEngine instance
ce = CE()
# selectByAttribute function: Select objects based on the attribute name and value
def selectByAttribute(attr, value):
objects = ce.getObjectsFrom(ce.scene)
selection = []
for o in objects:
attrvalue = ce.getAttribute(o, attr)
if attrvalue == value:
selection.append(o)
ce.setSelection(selection)
# Class defining the GUI components
class InputFrame(JFrame, ActionListener):
def __init__(self):
self.createAndShowGUI()
def createAndShowGUI(self):
self.setTitle("Attribute Input")
self.setSize(400, 150)
self.setLayout(BorderLayout())
# Add attribute name and value fields to the central panel
panel = JPanel()
panel.setLayout(GridLayout(2, 2, 10, 10))
# Attribute name input field
panel.add(JLabel("Attribute Name:"))
self.attrField = JTextField(15)
panel.add(self.attrField)
# Attribute value input field
panel.add(JLabel("Attribute Value:"))
self.valueField = JTextField(15)
panel.add(self.valueField)
# Add the panel to the center
self.add(panel, BorderLayout.CENTER)
# Add Execute and Close buttons to the bottom
buttonPanel = JPanel()
buttonPanel.setLayout(GridLayout(1, 2, 10, 10))
# Execute button
self.button = JButton("Search", actionPerformed=self.actionPerformed)
buttonPanel.add(self.button)
# Close button
self.closeButton = JButton("Cancel", actionPerformed=self.closeWindow)
buttonPanel.add(self.closeButton)
# Add the button panel to the bottom
self.add(buttonPanel, BorderLayout.SOUTH)
# Set the default close operation and make the GUI visible
self.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
self.setVisible(True)
# Function triggered when the button is clicked
def actionPerformed(self, event):
attr = self.attrField.getText()
value = self.valueField.getText()
selectByAttribute(attr, value)
print("Selected objects with attribute '{}' and value '{}'.".format(attr, value))
self.dispose()
# Function to close the window when the close button is clicked
def closeWindow(self, event):
self.dispose()
if __name__ == '__main__':
# Launch the GUI window
InputFrame()
I've modified the code to allow searching for numerical attribute values as well.
Please note that I'm a beginner in Python, so there might be some shortcomings.
# Last modified: 2024-08-31 16:00:00 KST
# Version: 1.7
# Requirement: Fix the issue float type attr value
'''
@author: desert
'''
from scripting import *
from javax.swing import JFrame, JLabel, JTextField, JButton, JPanel
from java.awt import GridLayout, BorderLayout
from java.awt.event import ActionListener
# Get a CityEngine instance
ce = CE()
# selectByAttribute function: Select objects based on the attribute name and value
def selectByAttribute(attr, value):
objects = ce.getObjectsFrom(ce.scene)
selection = []
for o in objects:
attrvalue = ce.getAttribute(o, attr)
print(type(attrvalue))
if isinstance(attrvalue,float) and attrvalue == float(value):
selection.append(o)
elif isinstance(attrvalue,str) and attrvalue == value:
selection.append(o)
ce.setSelection(selection)
# Class defining the GUI components
class InputFrame(JFrame, ActionListener):
def __init__(self):
self.createAndShowGUI()
def createAndShowGUI(self):
self.setTitle("Attribute Input")
self.setSize(400, 150)
self.setLayout(BorderLayout())
# Add attribute name and value fields to the central panel
panel = JPanel()
panel.setLayout(GridLayout(2, 2, 10, 10))
# Attribute name input field
panel.add(JLabel("Attribute Name:"))
self.attrField = JTextField(15)
panel.add(self.attrField)
# Attribute value input field
panel.add(JLabel("Attribute Value:"))
self.valueField = JTextField(15)
panel.add(self.valueField)
# Add the panel to the center
self.add(panel, BorderLayout.CENTER)
# Add Execute and Close buttons to the bottom
buttonPanel = JPanel()
buttonPanel.setLayout(GridLayout(1, 2, 10, 10))
# Execute button
self.button = JButton("Search", actionPerformed=self.actionPerformed)
buttonPanel.add(self.button)
# Close button
self.closeButton = JButton("Cancel", actionPerformed=self.closeWindow)
buttonPanel.add(self.closeButton)
# Add the button panel to the bottom
self.add(buttonPanel, BorderLayout.SOUTH)
# Set the default close operation and make the GUI visible
self.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
self.setVisible(True)
# Function triggered when the button is clicked
def actionPerformed(self, event):
attr = self.attrField.getText()
value = self.valueField.getText()
selectByAttribute(attr, value)
print("Selected objects with attribute '{}' and value '{}'.".format(attr, value))
self.dispose()
# Function to close the window when the close button is clicked
def closeWindow(self, event):
self.dispose()
if __name__ == '__main__':
# Launch the GUI window
InputFrame()
Hi @desert,
Thanks for sharing your script with the community.
While its true that currently advanced selections based on attributes can be done using the python scripting interface only, a basic search for attributes is available directly in the Scene Editor:
For more details about the feature checkout the online help:
CityEngine Help: Scene Editor: Additional layer options
If you are interested in advanced search capabilities through a GUI interface, I encourage you to create a new post in the Ideas forum!
Cheers
Jonas
It seems I did something unnecessary without even thoroughly reading the manual I had checked before. I will carefully read the help section again. Thank you for pointing it out.
I wouldn't say its unnecessary because you can do advanced filtering and selection using python. For instance using your script you can search for specific key/value pairs while the search bar in the Scene Editor will match everything with the entered name.