Print at Oct 5, 2026, 8:51:55 PM
Posts: 99   Pages: 10   [ Previous Page | 1 2 3 4 5 6 7 8 9 10 ]
View all posts in this thread on one page
Posted by Xlance at Jun 27, 2026, 11:36:14 PM
Re: Staircase generator plug-in
@el_dario
Version 4.2 or later will be posted on sourceforge as soon as it's ready smile
----------------------------------------

Windows 64bit | Intel i7 | SH3D 8.0 + Plugins

Posted by el_dario at Jun 30, 2026, 12:38:05 PM
Re: Staircase generator plug-in
Thank you for your reply, @Xlance! I eagerly await the release of version 4.2, so I can try out these new features! :)

Posted by Xlance at Aug 7, 2026, 8:30:20 AM
Re: Staircase generator plug-in
NEW in version 4.2
Import Plan image of Staircase in 2D Shape Designer and Trace it to get Precise cutout *.svg path

1.CHOOSE Plan image of Staircase to Trace

2.TRACE then SAVE values of custom cutout into *.svg

3.LOAD *.svg file then COPY values of custom cutout

4.PASTE values of custom cutout into field (make sure to un-select 'generate cutout' check box)

5.CREATE staircase (custom cutout will be embedded with model)



Take screenshot
https://ibb.co/Hp7L50hg

Open 2D Shape Designer and choose image to load
https://ibb.co/kgcqv5DS

Trace outline/cutout then save in *.svg
https://ibb.co/hJPJcnb7

Load *.svg and copy values
https://ibb.co/SjhZx5Z

Paste values into custom cutout field (make sure to un-select 'generate cutout' check box)
https://ibb.co/21Pkb45G

Result
https://ibb.co/3Y0zDr4F
----------------------------------------

Windows 64bit | Intel i7 | SH3D 8.0 + Plugins

Posted by Keet at Aug 7, 2026, 9:53:06 AM
Re: Staircase generator plug-in
Why so difficult? You can easily calculate an SVG cutout string using the v lines in a room object (or any other object where an outline can be calculated from). It is much easier to draw a room then the screenshot copies. Here's the code for it in PHP and C#.
Both code listings are made to to be readable by non-programmers too. This was a test for me so a little optimization is probably possible.
The C# code is close to Java code so should be easy to convert.
The PHP code is amateur work, I only use it for my websites.

C# code:
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace SH3D
{
public class SVG
{
// constructor
public SVG () {}

/// <summary>
/// Create an SVG cutout string from the given obj file
/// </summary>
/// <returns>
/// The SVG cutout string
/// </returns>
/// <param name='sourcefile'>
/// The obj file to use for creating the SVG string.
/// A cutout string is generated using the v lines in the first group, best result with a room object.
/// </param>
public string CreateSVGcutout (string sourcefile)
{
if (!File.Exists (sourcefile)) { return string.Empty; }

#region create vertice list
// Create an empty list to hold all vertices (v lines)
List<Vertice> vertices = new List<Vertice> ();

// Read all lines in the obj file into a string array
String[] lines = File.ReadAllLines (sourcefile);
bool start = false;

// For each line that starts with "v " create a Vertice object and add it to the vertices list.
// z is set to 0 by default, not used for a SVG cutout.
foreach (string line in lines) {
if (line.StartsWith ("v ")) {
start = true;
string[] parts = line.Split (new char[] {' '});
// 0 = "v", 1=X, 2=Z, 3=Y
Vertice v = new Vertice (double.Parse(parts [1]), double.Parse(parts [3]), 0.0d);
vertices.Add (v);
} else {
// First set of v lines done, ignore the rest
if (start) {
break;
}
}
}
#endregion create vertice list

#region object bounderies
// Get the object bounderies, I.E. the width and depth of the object
// These are needed to calculate the L points
// Calculating this enables processing objects that dont't have 0,0 as the position coordinates.
double minwidth = 0.0;
double maxwidth = 0.0;
double mindepth = 0.0;
double maxdepth = 0.0;
bool first = true;
foreach (Vertice v in vertices) {
if (first) {
minwidth = v.X;
maxwidth = v.X;
mindepth = v.Y;
maxdepth = v.Y;
first = false;
} else {
minwidth = Math.Min (minwidth, v.X);
maxwidth = Math.Max (maxwidth, v.X);
mindepth = Math.Min (mindepth, v.Y);
maxdepth = Math.Max (maxdepth, v.Y);
}
}

double width = 0.0d;
if (minwidth < 0) {
if (maxwidth < 0) { // - / -
width = Math.Abs (minwidth) - Math.Abs (maxwidth);
} else { // - / +
width = Math.Abs (minwidth) + maxwidth;
}
} else { // + / +
width = maxwidth - minwidth;
}

double depth = 0.0d;
if (mindepth < 0) {
if (maxdepth < 0) { // - / -
depth = Math.Abs (mindepth) - Math.Abs (maxdepth);
} else { // - / +
depth = Math.Abs (mindepth) + Math.Abs (maxdepth);
}
} else { // + / +
depth = maxdepth - mindepth;
}

// Recalculate the vertice points so they start from the correct origin
for (int i=0; i< vertices.Count; i++) {
vertices.X = vertices.X-minwidth;
vertices.Y = vertices.Y-mindepth;
}
#endregion object bounderies

#region create SVG string
string svg = "";
first = true;
foreach (Vertice v in vertices) {
if (first) {
// first starts with "M"
svg += "M" + Math.Round(v.X/width,4).ToString() + "," + Math.Round(v.Y/depth,4).ToString() + " ";
first = false;
} else {
// add L points
svg += "L" + Math.Round(v.X/width,4).ToString() + "," + Math.Round(v.Y/depth,4).ToString() + " ";
}
}
svg += "z"; // z = back to start (M)
#endregion create SVG string

// return the SVG string
return svg;
}
}
}


PHP code:
<?php
include_once "base.php";
if (session_id() == "") { session_start(); }

class SVGCutout {
// private $_exportpath = TMPPATH;
public $lines;

function __construct() {}

// CEILING&WALL cutout
function CreateSVGcutout(): string
{
$vertices = array();
$start = false;
foreach(preg_split("/((\r?\n)|(\r\n?))/", $this->lines) as $line) {
if (str_starts_with($line, 'v ')) {
$start = true;
$parts = preg_split('/\s+/', $line);
// 0 = "v", 1=X, 2=Z, 3=Y
$vertices[] = array($parts[1],$parts[3]);
} else {
if ($start === true) {
// ignore the rest.
break;
}
}
}

// get the object bounderies, I.E. the width and depth of the object
// these are needed to calculate the L points
$minw = 0.0; $maxw = 0.0; $mind = 0.0; $maxd = 0.0;
$first = true;

// get the object boundaries
for ($i = 0; $i < count($vertices); $i++) {
if ($first === true) {
$minw = (float)$vertices[$i][0];
$maxw = (float)$vertices[$i][0];
$mind = (float)$vertices[$i][1];
$maxd = (float)$vertices[$i][1];
$first = false;
} else {
$minw = min($minw, (float)$vertices[$i][0]);
$maxw = max($maxw, (float)$vertices[$i][0]);
$mind = min($mind, (float)$vertices[$i][1]);
$maxd = max($maxd, (float)$vertices[$i][1]);
}
}

// calculate the width and depth
$width = 0.0;
$depth = 0.0;
if ($minw < 0) {
if ($maxw < 0) { $width = abs($minw) - abs($maxw); }
else { $width = abs($minw) + $maxw; }
} else { $width = $maxw - $minw; }
if ($mind < 0) {
if ($maxd < 0) { $depth = abs($mind) - abs($maxd); }
else { $depth = abs($mind) + abs($maxd); }
} else { $depth = $maxd - $mind; }

// to avoid division by zero if either one gets to be 0
if ($width == 0) { return "The width is 0"; }
if ($depth == 0) { return "The depth is 0"; }

// create the svg string
$svg = "";
$first = true;
for ($i = 0; $i < count($vertices); $i++) {
// recalculate the vertice points so they start from the correct origin
$vertices[$i][0] = $vertices[$i][0]-$minw;
$vertices[$i][1] = $vertices[$i][1]-$mind;
// calculate the M and L values
if ($first === true) { $svg .= "M"; $first = false; }
else { $svg .= "L"; }
$svg .= (string)round(($vertices[$i][0])/$width,4) . "," . (string)round(($vertices[$i][1])/$depth,4) . " ";
}
$svg .= "z";

// $fs = fopen($this->_exportpath . "svgoutput.txt", "w");
// fwrite($fs,$svg);
// fclose($fs);

return $svg;
}
}
?>

----------------------------------------
Dodecagon.nl
1300+ 3D models, manuals, and projects

Posted by Xlance at Aug 7, 2026, 10:45:09 AM
Re: Staircase generator plug-in
An excellent solution. Thank You smile
However in many cases I need to get creative and design a cutout which does not correspond to model edges. e.g. circular for a T shaped
----------------------------------------

Windows 64bit | Intel i7 | SH3D 8.0 + Plugins

Posted by Keet at Aug 7, 2026, 11:23:05 AM
Re: Staircase generator plug-in
That's why this code solution is easier. You can draw a room in any form you need, for example a star or T and it will calculate the cutout. To be clear: this is independent from the staircase object, completely separate. It is as if you draw the outline as in your examples but now without screenshots and as a room object.
----------------------------------------
Dodecagon.nl
1300+ 3D models, manuals, and projects

Posted by Xlance at Aug 8, 2026, 12:09:39 PM
Re: Staircase generator plug-in
▼
Version 4.2 Released on Sourceforge
(This update took a LOT of time and effort ;-)
Enjoy

https://sourceforge.net/p/sweethome3d/plug-ins/60/#a9db
----------------------------------------

Windows 64bit | Intel i7 | SH3D 8.0 + Plugins

Posted by nckv at Aug 28, 2026, 5:53:28 PM
Re: Staircase generator plug-in
Hi, thanks for this nice plugin! Could you maybe add a function to make the "first stairs count" asymmetric, i.e. different counts for the bottom treads and the top treads?

So basically add also a "last stairs count" or something? Or maybe better names are "lower tread count" and "upper tread count"?

I have a staircase where this is like that.

Also, the latest version 4.2 is not detected by the Plugin Manager plugin yet!

Posted by dorin at Aug 31, 2026, 7:02:08 PM
Re: Staircase generator plug-in
Maybe this could help you.
----------------------------------------
A computer program does what you tell it to do, not what you want it to do. Murphy's Law
When all else fails, read the instructions. Murphy's Law
If you don't like "AS IS", DIY. Dorin's law

Posts: 99   Pages: 10   [ Previous Page | 1 2 3 4 5 6 7 8 9 10 ]