Keet
Advanced Member
Netherlands
Joined: Apr 8, 2022
Post Count: 1815
Status:
Offline
|
|
|
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
|