Fascinating photos reveal life in Iran before the revolution
The stunning photos of life across vibrant Iran in the 60s and 70s portray a seemingly cosmopolitan kingdom on the brink of change.
Mail Online (www.dailymail.co.uk)
The stunning photos of life across vibrant Iran in the 60s and 70s portray a seemingly cosmopolitan kingdom on the brink of change.
Mail Online (www.dailymail.co.uk)
I have a question regarding material libraries. I have prepared a Carpaint collection and am also going to prepare a water material pack. The question is that if the same name materials will be replaced? i.e. a car paint in my library is called 001red. Imagine there is another material in the Sketchup model by user and called 001red, I am wondering if RS will replace the same name with my material? To be more precise: How do material libraries in RS work?
@L-i-am I got a diploma in mathematics and was into algorithmic thinking. Then tried to learn architecture during university with my analytic mindset. So I see it like a procedure, not like those who do magic out of a black box. For some years, I had this chance to teach architecture, and after years, sometimes students call me to thank my way of teaching. I hope I have the chance again; this is the most satisfying job for me.
I have been developing a vault generator add-on for Blender 3D that is aimed to mimic RhinoVault (considering Blender cons/pros vs Rhino).
It tries to find the best compression-only form for the given input mesh. Recently, I used Gemini to translate it to work with SketchUp. It is in its early stages and would be fine if anyone helps me to improve it.
# ============================================================
# SKETCHUP FOLDING VAULTS V4 (Robust Non-Flat Mesh + Red Anchors) | By Majid Yeganegi AI optimization -2025 Nov.
# ============================================================
require 'sketchup.rb'
module VaultPlugin
# --- 1. Math Helper Classes (Unchanged for performance) ---
class SparseMatrix
attr_reader :n_rows
def initialize(n_rows)
@n_rows = n_rows
@rows = Hash.new { |h, k| h[k] = {} }
end
def add(r, c, val)
return if r >= @n_rows || c >= @n_rows
@rows[r][c] ||= 0.0
@rows[r][c] += val
end
def dot(vec)
result = Array.new(@n_rows, 0.0)
@rows.each do |r_idx, col_data|
sum = 0.0
col_data.each { |c_idx, val| sum += val * vec[c_idx] }
result[r_idx] = sum
end
result
end
end
class VectorMath
def self.sub(a, b); a.zip(b).map { |x, y| x - y }; end
def self.add(a, b); a.zip(b).map { |x, y| x + y }; end
def self.scale(vec, s); vec.map { |x| x * s }; end
def self.dot(a, b); a.each_with_index.reduce(0) { |sum, (val, i)| sum + val * b[i] }; end
end
# --- 2. CG Solver ---
def self.cg_solve(matrix, b, x0, max_iter, tol)
x = x0.dup
r = VectorMath.sub(b, matrix.dot(x))
p = r.dup
rsold = VectorMath.dot(r, r)
max_iter.times do
ap = matrix.dot(p)
p_ap = VectorMath.dot(p, ap)
break if p_ap.abs < 1e-15
alpha = rsold / p_ap
x = VectorMath.add(x, VectorMath.scale(p, alpha))
r = VectorMath.sub(r, VectorMath.scale(ap, alpha))
rsnew = VectorMath.dot(r, r)
break if Math.sqrt(rsnew) < tol
p = VectorMath.add(r, VectorMath.scale(p, rsnew / rsold))
rsold = rsnew
end
return x
end
# --- 3. Helper: Check if Material is RED ---
def self.is_red?(entity)
return false unless entity.material
c = entity.material.color
# Check for Pure Red (255, 0, 0) or close to it
return true if c.red > 200 && c.green < 50 && c.blue < 50
return false
end
# --- 4. Main Process ---
def self.process_mesh(selection_mesh, density_input, load_input, scale_factor, iterations)
model = Sketchup.active_model
entities = model.active_entities
# A. Topology Extraction
verts = []
v_to_id = {}
faces = selection_mesh.grep(Sketchup::Face)
if faces.empty?
UI.messagebox("Please select a Mesh (Faces) first.")
return
end
faces.each do |f|
f.vertices.each do |v|
unless v_to_id.key?(v.entityID)
v_to_id[v.entityID] = verts.length
verts << v
end
end
end
n = verts.length
# B. Explicit Anchor Detection (THE "RED" RULE ONLY)
anchors = []
# Check 1: Red Faces
faces.each { |f| anchors.concat(f.vertices.map { |v| v_to_id[v.entityID] }) if is_red?(f) }
# Check 2: Red Edges
edges = faces.map { |f| f.edges }.flatten.uniq
edges.each do |e|
if is_red?(e)
anchors << v_to_id[e.start.entityID]
anchors << v_to_id[e.end.entityID]
end
end
anchors = anchors.uniq
if anchors.empty?
UI.messagebox("Error: No RED anchors found! The mesh will float freely.\nPlease paint at least one edge or face RED.")
return
end
# C. Index Mapping
free_map = []
global_to_free = {}
free_count = 0
(0...n).each do |i|
unless anchors.include?(i)
free_map << i
global_to_free[i] = free_count
free_count += 1
end
end
n_free = free_map.length
if n_free == 0
UI.messagebox("Error: All selected vertices are anchors. Nothing to calculate.")
return
end
# D. Build Edges Index
edges_idx = edges.map do |e|
id1 = v_to_id[e.start.entityID]
id2 = v_to_id[e.end.entityID]
[id1, id2] if id1 && id2
end.compact
# E. TNA Setup & Matrix Assembly
q_val = density_input
l_ff = SparseMatrix.new(n_free)
d = Array.new(n, 0.0)
# Build Laplacian (L_ff) and Diagonal (d)
edges_idx.each do |u, v|
w = q_val
d[u] += w
d[v] += w
u_free = !anchors.include?(u)
v_free = !anchors.include?(v)
if u_free && v_free
uf, vf = global_to_free[u], global_to_free[v]
l_ff.add(uf, vf, -w)
l_ff.add(vf, uf, -w)
end
end
free_map.each { |i_glob| l_ff.add(global_to_free[i_glob], global_to_free[i_glob], d[i_glob]) }
# F. Vertical Equilibrium (Solve for Final Z: Z_f)
# Initial Z-positions of free nodes (used as the initial guess and for calculating Delta Z later)
z_orig_free = Array.new(n_free)
free_map.each_with_index { |glob_idx, i| z_orig_free[i] = verts[glob_idx].position.z }
z_current = z_orig_free.dup
# Iterative Solve for Z_f
iterations.times do
rhs = Array.new(n_free, -load_input) # -Pf
edges_idx.each do |u, v|
w = q_val
u_free = !anchors.include?(u)
v_free = !anchors.include?(v)
# Contribution of fixed anchors to the RHS (-Lfa * Za)
if u_free && !v_free
rhs[global_to_free[u]] += w * verts[v].position.z
elsif !u_free && v_free
rhs[global_to_free[v]] += w * verts[u].position.z
end
end
z_current = cg_solve(l_ff, rhs, z_current, 200, 1e-5)
end
# G. Calculate and Apply Displacement (Delta Z)
# Delta Z = Z_final - Z_original. This is the displacement vector.
# It will be negative for a hanging form (since Z_f < Z_orig_f).
delta_z = VectorMath.sub(z_current, z_orig_free)
model.start_operation("Generate Vault", true)
group = entities.add_group
mesh_out = Geom::PolygonMesh.new
final_pts = []
# Use the sign of the scale factor to determine the flip
# scale_factor = -5.0 means: flip the negative displacement (to positive) and scale by 5.0
scale = scale_factor
(0...n).each do |i|
v_orig = verts[i].position
if anchors.include?(i)
final_pts << v_orig # Anchors stay at their original Z
else
dz_calc = delta_z[global_to_free[i]]
# Z_final = Z_original + (Delta Z * Scale)
# If Delta Z is negative (hanging form) and Scale is negative (-5.0),
# the result is positive displacement, creating the arch/vault.
z_final = v_orig.z + (dz_calc * scale)
final_pts << [v_orig.x, v_orig.y, z_final]
end
end
# Reconstruct faces
faces.each do |f|
idxs = f.vertices.map { |v| v_to_id[v.entityID] }
mesh_out.add_polygon(idxs.map { |k| final_pts[k] })
end
group.entities.add_faces_from_mesh(mesh_out)
group.name = "Vault_Result"
group.material = "White"
group.entities.grep(Sketchup::Edge).each { |e| e.soft = true; e.smooth = true }
model.commit_operation
end
# --- 5. UI Dialog ---
def self.show_dialog
prompts = ["Force Density (Stiffness)", "Load", "Height Scale (Multiplier)", "Iterations"]
# Default Scale set to 5.0, as requested.
defaults = [1.0, 1.0, 5.0, 30]
input = UI.inputbox(prompts, defaults, "TNA Settings")
return unless input
sel = Sketchup.active_model.selection
self.process_mesh(sel, input[0], input[1], input[2], input[3])
end
unless file_loaded?(__FILE__)
menu = UI.menu('Plugins')
menu.add_item('Create Vault (TNA)') { self.show_dialog }
file_loaded(__FILE__)
end
end

Just imagine they could be plans/sections/facades of buildings such as houses, complexes, hospitals, hotels, etc...

Let's continue with the letter I:
As usual, I start from 2D sketches:

The style is deliverable with the model: https://3dwarehouse.sketchup.com/model/30865223-c310-46bb-9743-46d655302747/An-H-building
Finally modeled an H building to see how it will come.

link to the model:
https://3dwarehouse.sketchup.com/model/30865223-c310-46bb-9743-46d655302747/An-H-building
I said to myself: Try your imagination with H, then try to make them 3D as well
This is really great, and thank you for sharing. You did the right job and well deserve what you got! I wish for way better upcoming days man!
I said to myself: Try your imagination with H, then try to make them 3D as well

I wish I could teach how to paint watercolors (online or in person)
If this is me only one who likes the vibe of old cities?
And one more old Eindhoven:

@Rich-O-Brien Woha! I am left speechless!
What an impressive 3D environment! What piece of software are you using?