added Revit 2022 SDK minus except *rvt and *rfa

This commit is contained in:
Jeremy Tammik
2021-04-20 11:36:21 +02:00
parent 1133a82dc5
commit 7e327986e8
3034 changed files with 1245318 additions and 0 deletions
+179
View File
@@ -0,0 +1,179 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Collections;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Windows.Forms;
using System.Collections.Generic;
using Autodesk.Revit.DB.Architecture;
namespace Revit.SDK.Samples.WinderStairs.CS
{
/// <summary>
/// Implements the Revit add-in interface IExternalCommand
/// </summary>
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
[Autodesk.Revit.Attributes.Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)]
public class Command : IExternalCommand
{
/// <summary>
/// Implement this method as an external command for Revit.
/// </summary>
/// <param name="commandData">An object that is passed to the external application
/// which contains data related to the command,
/// such as the application object and active view.</param>
/// <param name="message">A message that can be set by the external application
/// which will be displayed if a failure or cancellation is returned by
/// the external command.</param>
/// <param name="elements">A set of elements to which the external application
/// can add elements that are to be highlighted in case of failure or cancellation.</param>
/// <returns>Return the status of the external command.
/// A result of Succeeded means that the API external method functioned as expected.
/// Cancelled can be used to signify that the user cancelled the external operation
/// at some point. Failure should be returned if the application is unable to proceed with
/// the operation.</returns>
public virtual Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
try
{
Document rvtDoc = commandData.Application.ActiveUIDocument.Document;
var selectionIds = commandData.Application.ActiveUIDocument.Selection.GetElementIds();
if (selectionIds.Count != 2 && selectionIds.Count != 3)
{
message += "Please select two (or three) connected line elements. E.g. two (or three) connected straight Walls or Model Lines.";
return Result.Cancelled;
}
List<ElementId> selectedIds = new List<ElementId>();
selectedIds.AddRange(selectionIds);
// Generate the winder creation parameters from selected elements.
IList<XYZ> controlPoints = WinderUtil.CalculateControlPoints(rvtDoc, selectedIds);
double runWidth = 0, treadDepth = 0;
GetStairsData(rvtDoc, out runWidth, out treadDepth);
IList<uint> maxCount = WinderUtil.CalculateMaxStepsCount(controlPoints, runWidth, treadDepth);
uint numStepsInCorner = 3;
double centerOffset = 0.0;
if (selectionIds.Count == 2)
{
// Create L-Winder
using (LWinderOptions options = new LWinderOptions())
{
options.NumStepsAtStart = maxCount[0];
options.NumStepsAtEnd = maxCount[1];
options.NumStepsInCorner = numStepsInCorner;
options.RunWidth = runWidth;
options.CenterOffsetE = centerOffset;
options.CenterOffsetF = centerOffset;
if (options.ShowDialog() == DialogResult.OK)
{
LWinder lwinder = new LWinder();
lwinder.NumStepsAtStart = options.NumStepsAtStart;
lwinder.NumStepsInCorner = options.NumStepsInCorner;
lwinder.NumStepsAtEnd = options.NumStepsAtEnd;
lwinder.RunWidth = options.RunWidth;
lwinder.TreadDepth = treadDepth;
lwinder.CenterOffsetE = options.CenterOffsetE;
lwinder.CenterOffsetF = options.CenterOffsetF;
AddInId activeid = options.DMU ? commandData.Application.ActiveAddInId : null;
WinderUpdater lwinderDMU = new WinderUpdater(lwinder,
selectedIds, rvtDoc, activeid, options.Sketch);
}
}
}
else if (selectionIds.Count == 3)
{
// Create U-Winder
using (UWinderOptions options = new UWinderOptions())
{
options.NumStepsAtStart = maxCount[0];
options.NumStepsInMiddle = maxCount[1];
options.NumStepsAtEnd = maxCount[2];
options.NumStepsInCorner1 = numStepsInCorner;
options.NumStepsInCorner2 = numStepsInCorner;
options.RunWidth = runWidth;
options.CenterOffsetE1 = centerOffset;
options.CenterOffsetF1 = centerOffset;
options.CenterOffsetE2 = centerOffset;
options.CenterOffsetF2 = centerOffset;
if (options.ShowDialog() == DialogResult.OK)
{
UWinder uwinder = new UWinder();
uwinder.NumStepsAtStart = options.NumStepsAtStart;
uwinder.NumStepsInCorner1 = options.NumStepsInCorner1;
uwinder.NumStepsInMiddle = options.NumStepsInMiddle;
uwinder.NumStepsInCorner2 = options.NumStepsInCorner2;
uwinder.NumStepsAtEnd = options.NumStepsAtEnd;
uwinder.RunWidth = options.RunWidth;
uwinder.TreadDepth = treadDepth;
uwinder.CenterOffsetE1 = options.CenterOffsetE1;
uwinder.CenterOffsetF1 = options.CenterOffsetF1;
uwinder.CenterOffsetE2 = options.CenterOffsetE2;
uwinder.CenterOffsetF2 = options.CenterOffsetF2;
AddInId activeid = options.DMU ? commandData.Application.ActiveAddInId : null;
WinderUpdater uwinderDMU = new WinderUpdater(uwinder,
selectedIds, rvtDoc, activeid, options.Sketch);
}
}
}
return Result.Succeeded;
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}
/// <summary>
/// Retrieve the system default stairs data, like run width and tread depth.
/// </summary>
/// <param name="rvtDoc">Revit Document</param>
/// <param name="runWidth">Stairs run width</param>
/// <param name="treadDepth">Stairs tread depth</param>
private void GetStairsData(Document rvtDoc, out double runWidth, out double treadDepth)
{
FilteredElementCollector filterLevels = new FilteredElementCollector(rvtDoc);
var levels = filterLevels.OfClass(typeof(Level)).ToElements();
if (levels.Count < 2)
{
throw new InvalidOperationException("Need two Levels to create Stairs.");
}
List<Element> levelList = new List<Element>();
levelList.AddRange(levels);
levelList.Sort((a, b) => { return ((Level)a).Elevation.CompareTo(((Level)b).Elevation); });
using (StairsEditScope stairsMode = new StairsEditScope(rvtDoc, "DUMMY STAIRS SCOPE"))
{
var stairsId = stairsMode.Start(levelList[0].Id, levelList[1].Id);
Stairs stairs = rvtDoc.GetElement(stairsId) as Stairs;
StairsType stairsType = rvtDoc.GetElement(stairs.GetTypeId()) as StairsType;
runWidth = stairsType.MinRunWidth;
treadDepth = stairs.ActualTreadDepth;
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

@@ -0,0 +1,270 @@
namespace Revit.SDK.Samples.WinderStairs.CS
{
partial class LWinderOptions
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.okButton = new System.Windows.Forms.Button();
this.numAtStartTextBox = new System.Windows.Forms.TextBox();
this.numInCornerTextBox = new System.Windows.Forms.TextBox();
this.numAtEndTextBox = new System.Windows.Forms.TextBox();
this.runWidthTextBox = new System.Windows.Forms.TextBox();
this.startStepLabel = new System.Windows.Forms.Label();
this.cornerStepsNLabel = new System.Windows.Forms.Label();
this.endStepsLabel = new System.Windows.Forms.Label();
this.runWidthLabel = new System.Windows.Forms.Label();
this.cancelButton = new System.Windows.Forms.Button();
this.previewPictureBox = new System.Windows.Forms.PictureBox();
this.inputParamGroupBox = new System.Windows.Forms.GroupBox();
this.centerOffsetFLabel = new System.Windows.Forms.Label();
this.centerOffsetELabel = new System.Windows.Forms.Label();
this.centerOffsetFTextBox = new System.Windows.Forms.TextBox();
this.centerOffsetETextBox = new System.Windows.Forms.TextBox();
this.dmuCheckBox = new System.Windows.Forms.CheckBox();
this.sketchCheckBox = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).BeginInit();
this.inputParamGroupBox.SuspendLayout();
this.SuspendLayout();
//
// okButton
//
this.okButton.Location = new System.Drawing.Point(190, 279);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 26);
this.okButton.TabIndex = 0;
this.okButton.Text = "OK";
this.okButton.UseVisualStyleBackColor = true;
this.okButton.Click += new System.EventHandler(this.okButton_Click);
//
// numAtStartTextBox
//
this.numAtStartTextBox.Location = new System.Drawing.Point(113, 64);
this.numAtStartTextBox.Name = "numAtStartTextBox";
this.numAtStartTextBox.Size = new System.Drawing.Size(100, 20);
this.numAtStartTextBox.TabIndex = 1;
//
// numInCornerTextBox
//
this.numInCornerTextBox.Location = new System.Drawing.Point(113, 124);
this.numInCornerTextBox.Name = "numInCornerTextBox";
this.numInCornerTextBox.Size = new System.Drawing.Size(100, 20);
this.numInCornerTextBox.TabIndex = 2;
//
// numAtEndTextBox
//
this.numAtEndTextBox.Location = new System.Drawing.Point(113, 94);
this.numAtEndTextBox.Name = "numAtEndTextBox";
this.numAtEndTextBox.Size = new System.Drawing.Size(100, 20);
this.numAtEndTextBox.TabIndex = 3;
//
// runWidthTextBox
//
this.runWidthTextBox.Location = new System.Drawing.Point(113, 34);
this.runWidthTextBox.Name = "runWidthTextBox";
this.runWidthTextBox.Size = new System.Drawing.Size(100, 20);
this.runWidthTextBox.TabIndex = 4;
//
// startStepLabel
//
this.startStepLabel.AutoSize = true;
this.startStepLabel.Location = new System.Drawing.Point(24, 64);
this.startStepLabel.Name = "startStepLabel";
this.startStepLabel.Size = new System.Drawing.Size(78, 13);
this.startStepLabel.TabIndex = 6;
this.startStepLabel.Text = "Start Steps (A):";
//
// cornerStepsNLabel
//
this.cornerStepsNLabel.AutoSize = true;
this.cornerStepsNLabel.Location = new System.Drawing.Point(14, 124);
this.cornerStepsNLabel.Name = "cornerStepsNLabel";
this.cornerStepsNLabel.Size = new System.Drawing.Size(88, 13);
this.cornerStepsNLabel.TabIndex = 7;
this.cornerStepsNLabel.Text = "Corner Steps (N):";
//
// endStepsLabel
//
this.endStepsLabel.AutoSize = true;
this.endStepsLabel.Location = new System.Drawing.Point(27, 94);
this.endStepsLabel.Name = "endStepsLabel";
this.endStepsLabel.Size = new System.Drawing.Size(75, 13);
this.endStepsLabel.TabIndex = 8;
this.endStepsLabel.Text = "End Steps (B):";
//
// runWidthLabel
//
this.runWidthLabel.AutoSize = true;
this.runWidthLabel.Location = new System.Drawing.Point(25, 34);
this.runWidthLabel.Name = "runWidthLabel";
this.runWidthLabel.Size = new System.Drawing.Size(77, 13);
this.runWidthLabel.TabIndex = 9;
this.runWidthLabel.Text = "Run Width (C):";
//
// cancelButton
//
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(282, 279);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(75, 26);
this.cancelButton.TabIndex = 0;
this.cancelButton.Text = "Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
//
// previewPictureBox
//
this.previewPictureBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.previewPictureBox.Image = global::Revit.SDK.Samples.WinderStairs.CS.Properties.Resources.LWinder;
this.previewPictureBox.Location = new System.Drawing.Point(258, 12);
this.previewPictureBox.Name = "previewPictureBox";
this.previewPictureBox.Size = new System.Drawing.Size(269, 234);
this.previewPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.previewPictureBox.TabIndex = 5;
this.previewPictureBox.TabStop = false;
//
// inputParamGroupBox
//
this.inputParamGroupBox.Controls.Add(this.startStepLabel);
this.inputParamGroupBox.Controls.Add(this.runWidthLabel);
this.inputParamGroupBox.Controls.Add(this.numAtStartTextBox);
this.inputParamGroupBox.Controls.Add(this.centerOffsetFLabel);
this.inputParamGroupBox.Controls.Add(this.centerOffsetELabel);
this.inputParamGroupBox.Controls.Add(this.endStepsLabel);
this.inputParamGroupBox.Controls.Add(this.numInCornerTextBox);
this.inputParamGroupBox.Controls.Add(this.cornerStepsNLabel);
this.inputParamGroupBox.Controls.Add(this.centerOffsetFTextBox);
this.inputParamGroupBox.Controls.Add(this.centerOffsetETextBox);
this.inputParamGroupBox.Controls.Add(this.numAtEndTextBox);
this.inputParamGroupBox.Controls.Add(this.runWidthTextBox);
this.inputParamGroupBox.Location = new System.Drawing.Point(12, 12);
this.inputParamGroupBox.Name = "inputParamGroupBox";
this.inputParamGroupBox.Size = new System.Drawing.Size(229, 234);
this.inputParamGroupBox.TabIndex = 10;
this.inputParamGroupBox.TabStop = false;
this.inputParamGroupBox.Text = "Input Parameters";
//
// centerOffsetFLabel
//
this.centerOffsetFLabel.AutoSize = true;
this.centerOffsetFLabel.Location = new System.Drawing.Point(15, 184);
this.centerOffsetFLabel.Name = "centerOffsetFLabel";
this.centerOffsetFLabel.Size = new System.Drawing.Size(87, 13);
this.centerOffsetFLabel.TabIndex = 8;
this.centerOffsetFLabel.Text = "Center Offset (F):";
//
// centerOffsetELabel
//
this.centerOffsetELabel.AutoSize = true;
this.centerOffsetELabel.Location = new System.Drawing.Point(14, 154);
this.centerOffsetELabel.Name = "centerOffsetELabel";
this.centerOffsetELabel.Size = new System.Drawing.Size(88, 13);
this.centerOffsetELabel.TabIndex = 8;
this.centerOffsetELabel.Text = "Center Offset (E):";
//
// centerOffsetFTextBox
//
this.centerOffsetFTextBox.Location = new System.Drawing.Point(113, 184);
this.centerOffsetFTextBox.Name = "centerOffsetFTextBox";
this.centerOffsetFTextBox.Size = new System.Drawing.Size(100, 20);
this.centerOffsetFTextBox.TabIndex = 3;
//
// centerOffsetETextBox
//
this.centerOffsetETextBox.Location = new System.Drawing.Point(113, 154);
this.centerOffsetETextBox.Name = "centerOffsetETextBox";
this.centerOffsetETextBox.Size = new System.Drawing.Size(100, 20);
this.centerOffsetETextBox.TabIndex = 3;
//
// dmuCheckBox
//
this.dmuCheckBox.AutoSize = true;
this.dmuCheckBox.Location = new System.Drawing.Point(378, 285);
this.dmuCheckBox.Name = "dmuCheckBox";
this.dmuCheckBox.Size = new System.Drawing.Size(51, 17);
this.dmuCheckBox.TabIndex = 11;
this.dmuCheckBox.Text = "DMU";
this.dmuCheckBox.UseVisualStyleBackColor = true;
//
// sketchCheckBox
//
this.sketchCheckBox.AutoSize = true;
this.sketchCheckBox.Location = new System.Drawing.Point(440, 285);
this.sketchCheckBox.Name = "sketchCheckBox";
this.sketchCheckBox.Size = new System.Drawing.Size(60, 17);
this.sketchCheckBox.TabIndex = 24;
this.sketchCheckBox.Text = "Sketch";
this.sketchCheckBox.UseVisualStyleBackColor = true;
//
// LWinderOptions
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(546, 324);
this.ControlBox = false;
this.Controls.Add(this.sketchCheckBox);
this.Controls.Add(this.dmuCheckBox);
this.Controls.Add(this.inputParamGroupBox);
this.Controls.Add(this.previewPictureBox);
this.Controls.Add(this.cancelButton);
this.Controls.Add(this.okButton);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Name = "LWinderOptions";
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "L-Winder Options";
((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).EndInit();
this.inputParamGroupBox.ResumeLayout(false);
this.inputParamGroupBox.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button okButton;
private System.Windows.Forms.TextBox numAtStartTextBox;
private System.Windows.Forms.TextBox numInCornerTextBox;
private System.Windows.Forms.TextBox numAtEndTextBox;
private System.Windows.Forms.TextBox runWidthTextBox;
private System.Windows.Forms.PictureBox previewPictureBox;
private System.Windows.Forms.Label startStepLabel;
private System.Windows.Forms.Label cornerStepsNLabel;
private System.Windows.Forms.Label endStepsLabel;
private System.Windows.Forms.Label runWidthLabel;
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.GroupBox inputParamGroupBox;
private System.Windows.Forms.Label centerOffsetFLabel;
private System.Windows.Forms.Label centerOffsetELabel;
private System.Windows.Forms.TextBox centerOffsetFTextBox;
private System.Windows.Forms.TextBox centerOffsetETextBox;
private System.Windows.Forms.CheckBox dmuCheckBox;
private System.Windows.Forms.CheckBox sketchCheckBox;
}
}
@@ -0,0 +1,240 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Windows.Forms;
using Autodesk.Revit.UI;
namespace Revit.SDK.Samples.WinderStairs.CS
{
/// <summary>
/// This form is used to collect parameters for LWinder creation. It also validates the input
/// parameters and will warn if there is any invalid parameters when trying to submit the form.
/// </summary>
partial class LWinderOptions : Form
{
/// <summary>
/// Default constructor.
/// </summary>
public LWinderOptions()
{
InitializeComponent();
}
/// <summary>
/// Number of straight steps at start.
/// </summary>
public uint NumStepsAtStart
{
get
{
return uint.Parse(numAtStartTextBox.Text);
}
set
{
numAtStartTextBox.Text = value.ToString();
}
}
/// <summary>
/// Number of straight steps in winder corner.
/// </summary>
public uint NumStepsInCorner
{
get
{
return uint.Parse(numInCornerTextBox.Text);
}
set
{
numInCornerTextBox.Text = value.ToString();
}
}
/// <summary>
/// Number of straight steps at end.
/// </summary>
public uint NumStepsAtEnd
{
get
{
return uint.Parse(numAtEndTextBox.Text);
}
set
{
numAtEndTextBox.Text = value.ToString();
}
}
/// <summary>
/// Winder stairs run width.
/// </summary>
public double RunWidth
{
get
{
return double.Parse(runWidthTextBox.Text);
}
set
{
runWidthTextBox.Text = value.ToString();
}
}
/// <summary>
/// Center point offset distance from internal boundary.
/// </summary>
public double CenterOffsetE
{
get
{
return double.Parse(centerOffsetETextBox.Text);
}
set
{
centerOffsetETextBox.Text = value.ToString();
}
}
/// <summary>
/// Center point offset distance from internal boundary.
/// </summary>
public double CenterOffsetF
{
get
{
return double.Parse(centerOffsetFTextBox.Text);
}
set
{
centerOffsetFTextBox.Text = value.ToString();
}
}
/// <summary>
/// A switch indicates whether to support DMU(dynamic model update).
/// </summary>
public bool DMU
{
get
{
return dmuCheckBox.Checked;
}
}
/// <summary>
/// A switch to control the sketch drawing of winder stairs.
/// </summary>
public bool Sketch
{
get
{
return sketchCheckBox.Checked;
}
}
/// <summary>
/// Validate the UI input and it will warn if there are invalid user inputs.
/// </summary>
/// <returns>true if all input is fine.</returns>
private bool ValidateInput()
{
double runWidth;
if (!double.TryParse(runWidthTextBox.Text, out runWidth) || runWidth < 1.0e-6)
{
TaskDialog.Show("L-Winder Warning", "Run Width should be positive double", TaskDialogCommonButtons.Ok);
runWidthTextBox.Focus();
runWidthTextBox.SelectAll();
return false;
}
uint numAtStart;
if (!uint.TryParse(numAtStartTextBox.Text, out numAtStart))
{
TaskDialog.Show("L-Winder Warning", "Start steps should be unsigned integer", TaskDialogCommonButtons.Ok);
numAtStartTextBox.Focus();
numAtStartTextBox.SelectAll();
return false;
}
uint numAtEnd;
if (!uint.TryParse(numAtEndTextBox.Text, out numAtEnd))
{
TaskDialog.Show("L-Winder Warning", "End steps should be unsigned integer", TaskDialogCommonButtons.Ok);
numAtEndTextBox.Focus();
numAtEndTextBox.SelectAll();
return false;
}
uint numInCorner;
if (!uint.TryParse(numInCornerTextBox.Text, out numInCorner) || numInCorner < 1)
{
TaskDialog.Show("L-Winder Warning", "Corner steps should be unsigned integer and >= 1", TaskDialogCommonButtons.Ok);
numInCornerTextBox.Focus();
numInCornerTextBox.SelectAll();
return false;
}
double offsetE;
if (!double.TryParse(centerOffsetETextBox.Text, out offsetE) || offsetE < 0.0)
{
TaskDialog.Show("L-Winder Warning", "Center offset (E) should be non-negative double", TaskDialogCommonButtons.Ok);
centerOffsetETextBox.Focus();
centerOffsetETextBox.SelectAll();
return false;
}
double offsetF;
if (!double.TryParse(centerOffsetFTextBox.Text, out offsetF) || offsetF < 0.0)
{
TaskDialog.Show("L-Winder Warning", "Center offset (F) should be non-negative double", TaskDialogCommonButtons.Ok);
centerOffsetFTextBox.Focus();
centerOffsetFTextBox.SelectAll();
return false;
}
return true;
}
/// <summary>
/// Submit the UI input.
/// </summary>
private void okButton_Click(object sender, EventArgs e)
{
if (ValidateInput())
{
this.Close();
this.DialogResult = DialogResult.OK;
}
}
/// <summary>
/// Cancel the UI input.
/// </summary>
private void cancelButton_Click(object sender, EventArgs e)
{
this.Close();
this.DialogResult = DialogResult.Cancel;
}
}
}
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

@@ -0,0 +1,358 @@
namespace Revit.SDK.Samples.WinderStairs.CS
{
partial class UWinderOptions
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.runWidthLabel = new System.Windows.Forms.Label();
this.endStepsLabel = new System.Windows.Forms.Label();
this.cornerStepsN1Label = new System.Windows.Forms.Label();
this.startStepsLabel = new System.Windows.Forms.Label();
this.runWidthTextBox = new System.Windows.Forms.TextBox();
this.numAtEndTextBox = new System.Windows.Forms.TextBox();
this.numInCorner1TextBox = new System.Windows.Forms.TextBox();
this.numAtStartTextBox = new System.Windows.Forms.TextBox();
this.cancelButton = new System.Windows.Forms.Button();
this.okButton = new System.Windows.Forms.Button();
this.previewPictureBox = new System.Windows.Forms.PictureBox();
this.numInMiddleTextBox = new System.Windows.Forms.TextBox();
this.numInCorner2TextBox = new System.Windows.Forms.TextBox();
this.middleStepsLabel = new System.Windows.Forms.Label();
this.cornerStepsN2Label = new System.Windows.Forms.Label();
this.inputParamGroupBox = new System.Windows.Forms.GroupBox();
this.centerOffsetF2Label = new System.Windows.Forms.Label();
this.centerOffsetE2Label = new System.Windows.Forms.Label();
this.centerOffsetF1Label = new System.Windows.Forms.Label();
this.centerOffsetF2TextBox = new System.Windows.Forms.TextBox();
this.centerOffsetE2TextBox = new System.Windows.Forms.TextBox();
this.centerOffsetF1TextBox = new System.Windows.Forms.TextBox();
this.centerOffsetE1TextBox = new System.Windows.Forms.TextBox();
this.centerOffsetE1Label = new System.Windows.Forms.Label();
this.dmuCheckBox = new System.Windows.Forms.CheckBox();
this.sketchCheckBox = new System.Windows.Forms.CheckBox();
((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).BeginInit();
this.inputParamGroupBox.SuspendLayout();
this.SuspendLayout();
//
// runWidthLabel
//
this.runWidthLabel.AutoSize = true;
this.runWidthLabel.Location = new System.Drawing.Point(33, 32);
this.runWidthLabel.Name = "runWidthLabel";
this.runWidthLabel.Size = new System.Drawing.Size(77, 13);
this.runWidthLabel.TabIndex = 20;
this.runWidthLabel.Text = "Run Width (C):";
//
// endStepsLabel
//
this.endStepsLabel.AutoSize = true;
this.endStepsLabel.Location = new System.Drawing.Point(29, 116);
this.endStepsLabel.Name = "endStepsLabel";
this.endStepsLabel.Size = new System.Drawing.Size(81, 13);
this.endStepsLabel.TabIndex = 19;
this.endStepsLabel.Text = "End Steps (A2):";
//
// cornerStepsN1Label
//
this.cornerStepsN1Label.AutoSize = true;
this.cornerStepsN1Label.Location = new System.Drawing.Point(16, 144);
this.cornerStepsN1Label.Name = "cornerStepsN1Label";
this.cornerStepsN1Label.Size = new System.Drawing.Size(94, 13);
this.cornerStepsN1Label.TabIndex = 18;
this.cornerStepsN1Label.Text = "Corner Steps (N1):";
//
// startStepsLabel
//
this.startStepsLabel.AutoSize = true;
this.startStepsLabel.Location = new System.Drawing.Point(26, 60);
this.startStepsLabel.Name = "startStepsLabel";
this.startStepsLabel.Size = new System.Drawing.Size(84, 13);
this.startStepsLabel.TabIndex = 17;
this.startStepsLabel.Text = "Start Steps (A1):";
//
// runWidthTextBox
//
this.runWidthTextBox.Location = new System.Drawing.Point(118, 32);
this.runWidthTextBox.Name = "runWidthTextBox";
this.runWidthTextBox.Size = new System.Drawing.Size(100, 20);
this.runWidthTextBox.TabIndex = 15;
//
// numAtEndTextBox
//
this.numAtEndTextBox.Location = new System.Drawing.Point(118, 116);
this.numAtEndTextBox.Name = "numAtEndTextBox";
this.numAtEndTextBox.Size = new System.Drawing.Size(100, 20);
this.numAtEndTextBox.TabIndex = 14;
//
// numInCorner1TextBox
//
this.numInCorner1TextBox.Location = new System.Drawing.Point(118, 144);
this.numInCorner1TextBox.Name = "numInCorner1TextBox";
this.numInCorner1TextBox.Size = new System.Drawing.Size(100, 20);
this.numInCorner1TextBox.TabIndex = 13;
//
// numAtStartTextBox
//
this.numAtStartTextBox.Location = new System.Drawing.Point(118, 60);
this.numAtStartTextBox.Name = "numAtStartTextBox";
this.numAtStartTextBox.Size = new System.Drawing.Size(100, 20);
this.numAtStartTextBox.TabIndex = 12;
//
// cancelButton
//
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.cancelButton.Location = new System.Drawing.Point(334, 346);
this.cancelButton.Name = "cancelButton";
this.cancelButton.Size = new System.Drawing.Size(75, 26);
this.cancelButton.TabIndex = 10;
this.cancelButton.Text = "Cancel";
this.cancelButton.UseVisualStyleBackColor = true;
this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
//
// okButton
//
this.okButton.Location = new System.Drawing.Point(242, 346);
this.okButton.Name = "okButton";
this.okButton.Size = new System.Drawing.Size(75, 26);
this.okButton.TabIndex = 11;
this.okButton.Text = "OK";
this.okButton.UseVisualStyleBackColor = true;
this.okButton.Click += new System.EventHandler(this.okButton_Click);
//
// previewPictureBox
//
this.previewPictureBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.previewPictureBox.Image = global::Revit.SDK.Samples.WinderStairs.CS.Properties.Resources.UWinder;
this.previewPictureBox.Location = new System.Drawing.Point(274, 23);
this.previewPictureBox.Name = "previewPictureBox";
this.previewPictureBox.Size = new System.Drawing.Size(360, 302);
this.previewPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.previewPictureBox.TabIndex = 16;
this.previewPictureBox.TabStop = false;
//
// numInMiddleTextBox
//
this.numInMiddleTextBox.Location = new System.Drawing.Point(118, 88);
this.numInMiddleTextBox.Name = "numInMiddleTextBox";
this.numInMiddleTextBox.Size = new System.Drawing.Size(100, 20);
this.numInMiddleTextBox.TabIndex = 14;
//
// numInCorner2TextBox
//
this.numInCorner2TextBox.Location = new System.Drawing.Point(118, 228);
this.numInCorner2TextBox.Name = "numInCorner2TextBox";
this.numInCorner2TextBox.Size = new System.Drawing.Size(100, 20);
this.numInCorner2TextBox.TabIndex = 14;
//
// middleStepsLabel
//
this.middleStepsLabel.AutoSize = true;
this.middleStepsLabel.Location = new System.Drawing.Point(23, 88);
this.middleStepsLabel.Name = "middleStepsLabel";
this.middleStepsLabel.Size = new System.Drawing.Size(87, 13);
this.middleStepsLabel.TabIndex = 19;
this.middleStepsLabel.Text = "Middle Steps (B):";
//
// cornerStepsN2Label
//
this.cornerStepsN2Label.AutoSize = true;
this.cornerStepsN2Label.Location = new System.Drawing.Point(16, 228);
this.cornerStepsN2Label.Name = "cornerStepsN2Label";
this.cornerStepsN2Label.Size = new System.Drawing.Size(94, 13);
this.cornerStepsN2Label.TabIndex = 19;
this.cornerStepsN2Label.Text = "Corner Steps (N2):";
//
// inputParamGroupBox
//
this.inputParamGroupBox.Controls.Add(this.centerOffsetF2Label);
this.inputParamGroupBox.Controls.Add(this.centerOffsetE2Label);
this.inputParamGroupBox.Controls.Add(this.centerOffsetF1Label);
this.inputParamGroupBox.Controls.Add(this.numInMiddleTextBox);
this.inputParamGroupBox.Controls.Add(this.runWidthLabel);
this.inputParamGroupBox.Controls.Add(this.numAtStartTextBox);
this.inputParamGroupBox.Controls.Add(this.middleStepsLabel);
this.inputParamGroupBox.Controls.Add(this.numInCorner1TextBox);
this.inputParamGroupBox.Controls.Add(this.cornerStepsN2Label);
this.inputParamGroupBox.Controls.Add(this.centerOffsetF2TextBox);
this.inputParamGroupBox.Controls.Add(this.centerOffsetE2TextBox);
this.inputParamGroupBox.Controls.Add(this.centerOffsetF1TextBox);
this.inputParamGroupBox.Controls.Add(this.centerOffsetE1TextBox);
this.inputParamGroupBox.Controls.Add(this.numAtEndTextBox);
this.inputParamGroupBox.Controls.Add(this.centerOffsetE1Label);
this.inputParamGroupBox.Controls.Add(this.endStepsLabel);
this.inputParamGroupBox.Controls.Add(this.numInCorner2TextBox);
this.inputParamGroupBox.Controls.Add(this.cornerStepsN1Label);
this.inputParamGroupBox.Controls.Add(this.runWidthTextBox);
this.inputParamGroupBox.Controls.Add(this.startStepsLabel);
this.inputParamGroupBox.Location = new System.Drawing.Point(12, 12);
this.inputParamGroupBox.Name = "inputParamGroupBox";
this.inputParamGroupBox.Size = new System.Drawing.Size(243, 313);
this.inputParamGroupBox.TabIndex = 21;
this.inputParamGroupBox.TabStop = false;
this.inputParamGroupBox.Text = "Input Parameters";
//
// centerOffsetF2Label
//
this.centerOffsetF2Label.AutoSize = true;
this.centerOffsetF2Label.Location = new System.Drawing.Point(17, 284);
this.centerOffsetF2Label.Name = "centerOffsetF2Label";
this.centerOffsetF2Label.Size = new System.Drawing.Size(93, 13);
this.centerOffsetF2Label.TabIndex = 23;
this.centerOffsetF2Label.Text = "Center Offset (F2):";
//
// centerOffsetE2Label
//
this.centerOffsetE2Label.AutoSize = true;
this.centerOffsetE2Label.Location = new System.Drawing.Point(16, 256);
this.centerOffsetE2Label.Name = "centerOffsetE2Label";
this.centerOffsetE2Label.Size = new System.Drawing.Size(94, 13);
this.centerOffsetE2Label.TabIndex = 22;
this.centerOffsetE2Label.Text = "Center Offset (E2):";
//
// centerOffsetF1Label
//
this.centerOffsetF1Label.AutoSize = true;
this.centerOffsetF1Label.Location = new System.Drawing.Point(17, 200);
this.centerOffsetF1Label.Name = "centerOffsetF1Label";
this.centerOffsetF1Label.Size = new System.Drawing.Size(93, 13);
this.centerOffsetF1Label.TabIndex = 21;
this.centerOffsetF1Label.Text = "Center Offset (F1):";
//
// centerOffsetF2TextBox
//
this.centerOffsetF2TextBox.Location = new System.Drawing.Point(118, 284);
this.centerOffsetF2TextBox.Name = "centerOffsetF2TextBox";
this.centerOffsetF2TextBox.Size = new System.Drawing.Size(100, 20);
this.centerOffsetF2TextBox.TabIndex = 14;
//
// centerOffsetE2TextBox
//
this.centerOffsetE2TextBox.Location = new System.Drawing.Point(118, 256);
this.centerOffsetE2TextBox.Name = "centerOffsetE2TextBox";
this.centerOffsetE2TextBox.Size = new System.Drawing.Size(100, 20);
this.centerOffsetE2TextBox.TabIndex = 14;
//
// centerOffsetF1TextBox
//
this.centerOffsetF1TextBox.Location = new System.Drawing.Point(118, 200);
this.centerOffsetF1TextBox.Name = "centerOffsetF1TextBox";
this.centerOffsetF1TextBox.Size = new System.Drawing.Size(100, 20);
this.centerOffsetF1TextBox.TabIndex = 14;
//
// centerOffsetE1TextBox
//
this.centerOffsetE1TextBox.Location = new System.Drawing.Point(118, 172);
this.centerOffsetE1TextBox.Name = "centerOffsetE1TextBox";
this.centerOffsetE1TextBox.Size = new System.Drawing.Size(100, 20);
this.centerOffsetE1TextBox.TabIndex = 14;
//
// centerOffsetE1Label
//
this.centerOffsetE1Label.AutoSize = true;
this.centerOffsetE1Label.Location = new System.Drawing.Point(16, 172);
this.centerOffsetE1Label.Name = "centerOffsetE1Label";
this.centerOffsetE1Label.Size = new System.Drawing.Size(94, 13);
this.centerOffsetE1Label.TabIndex = 19;
this.centerOffsetE1Label.Text = "Center Offset (E1):";
//
// dmuCheckBox
//
this.dmuCheckBox.AutoSize = true;
this.dmuCheckBox.Location = new System.Drawing.Point(434, 352);
this.dmuCheckBox.Name = "dmuCheckBox";
this.dmuCheckBox.Size = new System.Drawing.Size(51, 17);
this.dmuCheckBox.TabIndex = 22;
this.dmuCheckBox.Text = "DMU";
this.dmuCheckBox.UseVisualStyleBackColor = true;
//
// sketchCheckBox
//
this.sketchCheckBox.AutoSize = true;
this.sketchCheckBox.Location = new System.Drawing.Point(497, 352);
this.sketchCheckBox.Name = "sketchCheckBox";
this.sketchCheckBox.Size = new System.Drawing.Size(60, 17);
this.sketchCheckBox.TabIndex = 23;
this.sketchCheckBox.Text = "Sketch";
this.sketchCheckBox.UseVisualStyleBackColor = true;
//
// UWinderOptions
//
this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.cancelButton;
this.ClientSize = new System.Drawing.Size(648, 384);
this.ControlBox = false;
this.Controls.Add(this.sketchCheckBox);
this.Controls.Add(this.dmuCheckBox);
this.Controls.Add(this.inputParamGroupBox);
this.Controls.Add(this.previewPictureBox);
this.Controls.Add(this.cancelButton);
this.Controls.Add(this.okButton);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Name = "UWinderOptions";
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "U-Winder Options";
((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).EndInit();
this.inputParamGroupBox.ResumeLayout(false);
this.inputParamGroupBox.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label runWidthLabel;
private System.Windows.Forms.Label endStepsLabel;
private System.Windows.Forms.Label cornerStepsN1Label;
private System.Windows.Forms.Label startStepsLabel;
private System.Windows.Forms.PictureBox previewPictureBox;
private System.Windows.Forms.TextBox runWidthTextBox;
private System.Windows.Forms.TextBox numAtEndTextBox;
private System.Windows.Forms.TextBox numInCorner1TextBox;
private System.Windows.Forms.TextBox numAtStartTextBox;
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Button okButton;
private System.Windows.Forms.TextBox numInMiddleTextBox;
private System.Windows.Forms.TextBox numInCorner2TextBox;
private System.Windows.Forms.Label middleStepsLabel;
private System.Windows.Forms.Label cornerStepsN2Label;
private System.Windows.Forms.GroupBox inputParamGroupBox;
private System.Windows.Forms.TextBox centerOffsetF2TextBox;
private System.Windows.Forms.TextBox centerOffsetE2TextBox;
private System.Windows.Forms.TextBox centerOffsetF1TextBox;
private System.Windows.Forms.TextBox centerOffsetE1TextBox;
private System.Windows.Forms.Label centerOffsetF2Label;
private System.Windows.Forms.Label centerOffsetE2Label;
private System.Windows.Forms.Label centerOffsetF1Label;
private System.Windows.Forms.Label centerOffsetE1Label;
private System.Windows.Forms.CheckBox dmuCheckBox;
private System.Windows.Forms.CheckBox sketchCheckBox;
}
}
@@ -0,0 +1,336 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Windows.Forms;
using Autodesk.Revit.UI;
namespace Revit.SDK.Samples.WinderStairs.CS
{
/// <summary>
/// This form is used to collect parameters for UWinder creation. It also validates the input
/// parameters and will warn if there is any invalid parameters when trying to submit the form.
/// </summary>
partial class UWinderOptions : Form
{
/// <summary>
/// Default constructor.
/// </summary>
public UWinderOptions()
{
InitializeComponent();
}
/// <summary>
/// Number of straight steps at start.
/// </summary>
public uint NumStepsAtStart
{
get
{
return uint.Parse(numAtStartTextBox.Text);
}
set
{
numAtStartTextBox.Text = value.ToString();
}
}
/// <summary>
/// Number of steps in the first winder corner.
/// </summary>
public uint NumStepsInCorner1
{
get
{
return uint.Parse(numInCorner1TextBox.Text);
}
set
{
numInCorner1TextBox.Text = value.ToString();
}
}
/// <summary>
/// Number of straight steps in middle.
/// </summary>
public uint NumStepsInMiddle
{
get
{
return uint.Parse(numInMiddleTextBox.Text);
}
set
{
numInMiddleTextBox.Text = value.ToString();
}
}
/// <summary>
/// Number of steps in the second winder corner.
/// </summary>
public uint NumStepsInCorner2
{
get
{
return uint.Parse(numInCorner2TextBox.Text);
}
set
{
numInCorner2TextBox.Text = value.ToString();
}
}
/// <summary>
/// Number of straight steps at end.
/// </summary>
public uint NumStepsAtEnd
{
get
{
return uint.Parse(numAtEndTextBox.Text);
}
set
{
numAtEndTextBox.Text = value.ToString();
}
}
/// <summary>
/// Winder stairs run width.
/// </summary>
public double RunWidth
{
get
{
return double.Parse(runWidthTextBox.Text);
}
set
{
runWidthTextBox.Text = value.ToString();
}
}
/// <summary>
/// Center point offset distance from the first corner.
/// </summary>
public double CenterOffsetE1
{
get
{
return double.Parse(centerOffsetE1TextBox.Text);
}
set
{
centerOffsetE1TextBox.Text = value.ToString();
}
}
/// <summary>
/// Center point offset distance from the first corner.
/// </summary>
public double CenterOffsetF1
{
get
{
return double.Parse(centerOffsetF1TextBox.Text);
}
set
{
centerOffsetF1TextBox.Text = value.ToString();
}
}
/// <summary>
/// Center point offset distance from the second corner.
/// </summary>
public double CenterOffsetE2
{
get
{
return double.Parse(centerOffsetE2TextBox.Text);
}
set
{
centerOffsetE2TextBox.Text = value.ToString();
}
}
/// <summary>
/// Center point offset distance from the second corner.
/// </summary>
public double CenterOffsetF2
{
get
{
return double.Parse(centerOffsetF2TextBox.Text);
}
set
{
centerOffsetF2TextBox.Text = value.ToString();
}
}
/// <summary>
/// A switch indicates whether to support DMU(dynamic model update).
/// </summary>
public bool DMU
{
get
{
return dmuCheckBox.Checked;
}
}
/// <summary>
/// A switch to control the sketch drawing of winder stairs.
/// </summary>
public bool Sketch
{
get
{
return sketchCheckBox.Checked;
}
}
/// <summary>
/// Validate the UI input and it will warn if there are invalid user inputs.
/// </summary>
/// <returns>true if all input is fine.</returns>
bool ValidateInput()
{
double runWidth;
if (!double.TryParse(runWidthTextBox.Text, out runWidth) || runWidth < 1.0e-6)
{
TaskDialog.Show("U-Winder Warning", "Run Width should be positive double", TaskDialogCommonButtons.Ok);
runWidthTextBox.Focus();
runWidthTextBox.SelectAll();
return false;
}
uint numAtStart;
if (!uint.TryParse(numAtStartTextBox.Text, out numAtStart))
{
TaskDialog.Show("U-Winder Warning", "Start steps should be unsigned integer", TaskDialogCommonButtons.Ok);
numAtStartTextBox.Focus();
numAtStartTextBox.SelectAll();
return false;
}
uint numInMiddle;
if (!uint.TryParse(numInMiddleTextBox.Text, out numInMiddle))
{
TaskDialog.Show("U-Winder Warning", "Middle steps should be unsigned integer", TaskDialogCommonButtons.Ok);
numInMiddleTextBox.Focus();
numInMiddleTextBox.SelectAll();
return false;
}
uint numAtEnd;
if (!uint.TryParse(numAtEndTextBox.Text, out numAtEnd))
{
TaskDialog.Show("U-Winder Warning", "End steps should be unsigned integer", TaskDialogCommonButtons.Ok);
numAtEndTextBox.Focus();
numAtEndTextBox.SelectAll();
return false;
}
uint numInCorner1;
if (!uint.TryParse(numInCorner1TextBox.Text, out numInCorner1) || numInCorner1 < 1)
{
TaskDialog.Show("U-Winder Warning", "The first corner steps should be unsigned integer and >= 1", TaskDialogCommonButtons.Ok);
numInCorner1TextBox.Focus();
numInCorner1TextBox.SelectAll();
return false;
}
double offsetE1;
if (!double.TryParse(centerOffsetE1TextBox.Text, out offsetE1) || offsetE1 < 0.0)
{
TaskDialog.Show("U-Winder Warning", "Center offset (E1) should be non-negative double", TaskDialogCommonButtons.Ok);
centerOffsetE1TextBox.Focus();
centerOffsetE1TextBox.SelectAll();
return false;
}
double offsetF1;
if (!double.TryParse(centerOffsetF1TextBox.Text, out offsetF1) || offsetF1 < 0.0)
{
TaskDialog.Show("U-Winder Warning", "Center offset (F1) should be non-negative double", TaskDialogCommonButtons.Ok);
centerOffsetF1TextBox.Focus();
centerOffsetF1TextBox.SelectAll();
return false;
}
uint numInCorner2;
if (!uint.TryParse(numInCorner2TextBox.Text, out numInCorner2) || numInCorner2 < 1)
{
TaskDialog.Show("U-Winder Warning", "The second corner steps should be unsigned integer and >= 1", TaskDialogCommonButtons.Ok);
numInCorner2TextBox.Focus();
numInCorner2TextBox.SelectAll();
return false;
}
double offsetE2;
if (!double.TryParse(centerOffsetE2TextBox.Text, out offsetE2) || offsetE2 < 0.0)
{
TaskDialog.Show("U-Winder Warning", "Center offset (E2) should be non-negative double", TaskDialogCommonButtons.Ok);
centerOffsetE2TextBox.Focus();
centerOffsetE2TextBox.SelectAll();
return false;
}
double offsetF2;
if (!double.TryParse(centerOffsetF2TextBox.Text, out offsetF2) || offsetF2 < 0.0)
{
TaskDialog.Show("U-Winder Warning", "Center offset (F2) should be non-negative double", TaskDialogCommonButtons.Ok);
centerOffsetF2TextBox.Focus();
centerOffsetF2TextBox.SelectAll();
return false;
}
return true;
}
/// <summary>
/// Submit the UI input.
/// </summary>
private void okButton_Click(object sender, EventArgs e)
{
if (ValidateInput())
{
this.Close();
this.DialogResult = DialogResult.OK;
}
}
/// <summary>
/// Cancel the UI input.
/// </summary>
private void cancelButton_Click(object sender, EventArgs e)
{
this.Close();
this.DialogResult = DialogResult.Cancel;
}
}
}
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
@@ -0,0 +1,55 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("WinderStairs")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Copyright © Autodesk, Inc. 2014")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("702ffe14-86c8-41c6-855d-987108aee56b")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,83 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Revit.SDK.Samples.WinderStairs.CS.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Revit.SDK.Samples.WinderStairs.CS.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap LWinder {
get {
object obj = ResourceManager.GetObject("LWinder", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap UWinder {
get {
object obj = ResourceManager.GetObject("UWinder", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}
@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="LWinder" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Forms\LWinder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="UWinder" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Forms\UWinder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
<AddIn Type="Command">
<Assembly>WinderStairs.dll</Assembly>
<ClientId>62426733-26fb-4f2b-89da-93e1be7fe549</ClientId>
<FullClassName>Revit.SDK.Samples.WinderStairs.CS.Command</FullClassName>
<Text>Winder Stairs</Text>
<Description>API Sketched Winder Stairs</Description>
<VisibilityMode>AlwaysVisible</VisibilityMode>
<LanguageType>Unknown</LanguageType>
<VendorId>ADSK</VendorId>
</AddIn>
</RevitAddIns>
@@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{3DEDE48B-7FC9-4923-844C-3AE7A08D55E6}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Revit.SDK.Samples.WinderStairs.CS</RootNamespace>
<AssemblyName>WinderStairs</AssemblyName>
<StartupObject>
</StartupObject>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<DocumentationFile>bin\Debug\WinderStairs.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DocumentationFile>bin\Debug\WinderStairs.XML</DocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Command.cs" />
<Compile Include="Winders\WinderSinglePoint.cs" />
<Compile Include="Winders\WinderStraight.cs" />
<Compile Include="Winders\WinderCorner.cs" />
<Compile Include="WinderUpdater.cs" />
<Compile Include="Winders\LWinder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Winders\WinderUtil.cs" />
<Compile Include="Winders\UWinder.cs" />
<Compile Include="Forms\UWinderOptions.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\UWinderOptions.Designer.cs">
<DependentUpon>UWinderOptions.cs</DependentUpon>
</Compile>
<Compile Include="Winders\Winder.cs" />
<Compile Include="Forms\LWinderOptions.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Forms\LWinderOptions.Designer.cs">
<DependentUpon>LWinderOptions.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Forms\LWinderOptions.resx">
<DependentUpon>LWinderOptions.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Forms\UWinderOptions.resx">
<DependentUpon>UWinderOptions.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="Forms\LWinder.png" />
</ItemGroup>
<ItemGroup>
<None Include="Forms\UWinder.png" />
</ItemGroup>
<ItemGroup />
<Import Project="$(SolutionDir)VSProps\SDKSamples.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<PropertyGroup>
<PostBuildEvent>set FILEFORSAMPLEREG="$(SolutionDir)..\..\..\..\Regression\API\SDKSamples\UpdateSampleDllForRegression.pl"
if exist %25FILEFORSAMPLEREG%25 perl %25FILEFORSAMPLEREG%25 $(ProjectExt) "$(ProjectPath)" "$(TargetPath)" "$(SolutionDir)"</PostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
</PropertyGroup>
</Project>
@@ -0,0 +1,175 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB.Architecture;
namespace Revit.SDK.Samples.WinderStairs.CS
{
/// <summary>
/// This class implements IUpdater and IExternalEventHandler interfaces. It's mainly
/// for winder stairs creation and regeneration when its dependencies are being changed.
/// </summary>
class WinderUpdater : IUpdater, IExternalEventHandler
{
private UpdaterId m_updaterId = null;
private IList<ElementId> m_curveElements = null;
private ElementId m_winderRunId = ElementId.InvalidElementId;
private Winder m_winder = null;
private bool m_removeTheUpdater = false;
private bool m_drawSketch = false;
/// <summary>
/// Constructor to initialize the fields and create the winder stairs.
/// It also registers the updater if addinId is not null.
/// </summary>
/// <param name="winder">Winder to create winder stairs</param>
/// <param name="crvElements">Curve Elements to control the winder shape</param>
/// <param name="rvtDoc">Revit Document</param>
/// <param name="addinId">Active AddInId</param>
/// <param name="drawSketch">Switch to control the winder sketch drawing</param>
public WinderUpdater(Winder winder, IList<ElementId> crvElements,
Document rvtDoc, AddInId addinId, bool drawSketch)
{
m_curveElements = crvElements;
m_winder = winder;
m_drawSketch = drawSketch;
// Create the winder stairs
GenerateWinderStairs(rvtDoc);
// Register the updater if addinId is not null.
if (addinId != null)
{
// Register the updater
m_updaterId = new UpdaterId(addinId, Guid.NewGuid());
UpdaterRegistry.RegisterUpdater(this, rvtDoc);
// Add modification triggers
UpdaterRegistry.AddTrigger(m_updaterId, rvtDoc,
m_curveElements, Element.GetChangeTypeAny());
// Add deletion trigger
List<ElementId> deleteParents = new List<ElementId>();
deleteParents.AddRange(crvElements);
var stairRun = rvtDoc.GetElement(m_winderRunId) as StairsRun;
deleteParents.Add(stairRun.GetStairs().Id);
UpdaterRegistry.AddTrigger(m_updaterId, rvtDoc,
deleteParents, Element.GetChangeTypeElementDeletion());
}
}
/// <summary>
/// Create the winder stairs in the Document.
/// </summary>
/// <param name="rvtDoc">Revit Document.</param>
private void GenerateWinderStairs(Document rvtDoc)
{
if (m_removeTheUpdater)
{
// unregister this updater
UpdaterRegistry.UnregisterUpdater(m_updaterId, rvtDoc);
return;
}
// Create the winder
m_winder.ControlPoints = WinderUtil.CalculateControlPoints(rvtDoc, m_curveElements);
m_winder.Build(rvtDoc, m_drawSketch, ref m_winderRunId);
}
/// <summary>
/// Implementation of IUpdater.Execute method.
/// </summary>
void IUpdater.Execute(UpdaterData data)
{
// If there is any deleted elements, this updater need to be unregistered.
if (data.GetDeletedElementIds().Count != 0)
{
// set the unregistered flag,
// because it's not allowed to remove the executing updater.
m_removeTheUpdater = true;
}
// Raise the External Event
ExternalEvent exEvent = ExternalEvent.Create(this);
exEvent.Raise();
}
/// <summary>
/// Implementation of IUpdater.GetAdditionalInformation method.
/// </summary>
string IUpdater.GetAdditionalInformation()
{
return "API SKETCHED WINDER";
}
/// <summary>
/// Implementation of IUpdater.GetChangePriority method.
/// </summary>
ChangePriority IUpdater.GetChangePriority()
{
return ChangePriority.GridsLevelsReferencePlanes;
}
/// <summary>
/// Implementation of IUpdater.GetUpdaterId method.
/// </summary>
UpdaterId IUpdater.GetUpdaterId()
{
return m_updaterId;
}
/// <summary>
/// Implementation of IUpdater.GetUpdaterName method.
/// </summary>
string IUpdater.GetUpdaterName()
{
return "Revit.SDK.Samples.WinderStairs";
}
/// <summary>
/// Implementation of IExternalEventHandler.Execute method.
/// </summary>
void IExternalEventHandler.Execute(UIApplication app)
{
try
{
GenerateWinderStairs(app.ActiveUIDocument.Document);
}
catch (System.Exception ex)
{
TaskDialog.Show("WinderStairs",
"Can't generate the winder layout because " + ex.Message);
}
}
/// <summary>
/// Implementation of IExternalEventHandler.GetName method.
/// </summary>
string IExternalEventHandler.GetName()
{
return "Revit.SDK.Samples.WinderStairs";
}
}
}
@@ -0,0 +1,145 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using Autodesk.Revit.DB;
using System.Collections.Generic;
namespace Revit.SDK.Samples.WinderStairs.CS
{
/// <summary>
/// It represents an L-shape winder and consists of two straight runs and one winder corner.
/// </summary>
class LWinder : Winder
{
/// <summary>
/// Number of straight steps at start.
/// </summary>
public uint NumStepsAtStart { get; set; }
/// <summary>
/// Number of straight steps at end.
/// </summary>
public uint NumStepsAtEnd { get; set; }
/// <summary>
/// Number of winder steps in corner.
/// </summary>
public uint NumStepsInCorner { get; set; }
/// <summary>
/// CenterPoint Offset distance from the first inner boundary line of the corner.
/// </summary>
public double CenterOffsetE { get; set; }
/// <summary>
/// CenterPoint Offset distance from the second inner boundary line of the corner.
/// </summary>
public double CenterOffsetF { get; set; }
/// <summary>
/// Three points to determine the L-shape of the stairs.
/// </summary>
public override IList<XYZ> ControlPoints
{
get
{
return base.ControlPoints;
}
set
{
if (value.Count != 3)
{
throw new ArgumentException("The control points count must be 3 for LWinder.");
}
base.ControlPoints = value;
}
}
#region PRIVATE
/// <summary>
/// Winder Corner, connecting the first and the second straight runs.
/// </summary>
private WinderSinglePoint m_corner;
/// <summary>
/// The first straight run at start.
/// </summary>
private WinderStraight m_straightAtStart;
/// <summary>
/// The second straight run at end.
/// </summary>
private WinderStraight m_straightAtEnd;
/// <summary>
/// This method constructs the winder corner and two straight runs.
/// Please be sure the input properties being set properly before calling this method.
/// </summary>
private void Construct()
{
//
// Construct the winder corner.
//
XYZ dir1 = (ControlPoints[1] - ControlPoints[0]).Normalize();
XYZ dir2 = (ControlPoints[2] - ControlPoints[1]).Normalize();
m_corner = new WinderSinglePoint(ControlPoints[1], dir1, dir2, NumStepsInCorner);
m_corner.Construct(RunWidth, CenterOffsetE, CenterOffsetF);
//
// Construct two straight runs to connect to the winder corner.
//
XYZ startPnt = m_corner.StartPoint - TreadDepth * NumStepsAtStart * dir1;
XYZ endPnt = m_corner.EndPoint + TreadDepth * NumStepsAtEnd * dir2;
XYZ bisectDir = (dir2 - dir1).Normalize();
XYZ perpendicularDir1 = new XYZ(-dir1.Y, dir1.X, 0);
XYZ perpendicularDir2 = new XYZ(-dir2.Y, dir2.X, 0);
if (bisectDir.DotProduct(perpendicularDir1) < 0)
{
perpendicularDir1 = perpendicularDir1.Negate();
perpendicularDir2 = perpendicularDir2.Negate();
}
m_straightAtStart = new WinderStraight(
startPnt, m_corner.StartPoint, perpendicularDir1, NumStepsAtStart);
m_straightAtEnd = new WinderStraight(
m_corner.EndPoint, endPnt, perpendicularDir2, NumStepsAtEnd);
}
#endregion
/// <summary>
/// This method generates the sketch for L-shape winder stairs.
/// </summary>
protected override void GenerateSketch()
{
// Instantiate the corner and the two straight runs.
Construct();
// Generate sketch for winder corner and straight runs.
m_straightAtStart.GenerateSketch(
RunWidth, OuterBoundary, CenterWalkpath, InnerBoundary, RiserLines);
m_corner.GenerateSketch(
RunWidth, OuterBoundary, CenterWalkpath, InnerBoundary, RiserLines);
m_straightAtEnd.GenerateSketch(
RunWidth, OuterBoundary, CenterWalkpath, InnerBoundary, RiserLines);
}
}
}
@@ -0,0 +1,193 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using Autodesk.Revit.DB;
using System.Collections.Generic;
namespace Revit.SDK.Samples.WinderStairs.CS
{
/// <summary>
/// It represents a U-shape winder and consists of three straight runs and two winder corners.
/// </summary>
class UWinder : Winder
{
/// <summary>
/// Number of straight steps at start.
/// </summary>
public uint NumStepsAtStart { get; set; }
/// <summary>
/// Number of straight steps in middle.
/// </summary>
public uint NumStepsInMiddle { get; set; }
/// <summary>
/// Number of straight steps at end.
/// </summary>
public uint NumStepsAtEnd { get; set; }
/// <summary>
/// Number of winder steps in the first corner.
/// </summary>
public uint NumStepsInCorner1 { get; set; }
/// <summary>
/// CenterPoint Offset distance from the first inner boundary line of the first corner.
/// </summary>
public double CenterOffsetE1 { get; set; }
/// <summary>
/// CenterPoint Offset distance from the second inner boundary line of the first corner.
/// </summary>
public double CenterOffsetF1 { get; set; }
/// <summary>
/// Number of winder steps in the second corner.
/// </summary>
public uint NumStepsInCorner2 { get; set; }
/// <summary>
/// CenterPoint Offset distance from the first inner boundary line of the second corner.
/// </summary>
public double CenterOffsetE2 { get; set; }
/// <summary>
/// CenterPoint Offset distance from the second inner boundary line of the second corner.
/// </summary>
public double CenterOffsetF2 { get; set; }
/// <summary>
/// Four Points to determine the U-shape of the stairs.
/// </summary>
public override IList<XYZ> ControlPoints
{
get
{
return base.ControlPoints;
}
set
{
if (value.Count != 4)
{
throw new ArgumentException("The control points count must be 4 for UWinder.");
}
base.ControlPoints = value;
}
}
#region PRIVATE
/// <summary>
/// The first Winder Corner, connecting the first and the second straight runs.
/// </summary>
private WinderSinglePoint m_corner1st;
/// <summary>
/// The second Winder Corner, connecting the second and the third straight runs.
/// </summary>
private WinderSinglePoint m_corner2nd;
/// <summary>
/// The first straight run at start.
/// </summary>
private WinderStraight m_straightAtStart;
/// <summary>
/// The second straight run in middle.
/// </summary>
private WinderStraight m_straightInMiddle;
/// <summary>
/// The third straight run at end.
/// </summary>
private WinderStraight m_straightAtEnd;
/// <summary>
/// This method constructs two winder corners and three straight runs.
/// Please be sure the input properties being set properly before calling this method.
/// </summary>
private void Construct()
{
//
// Construct the first winder corner
//
XYZ dir1 = (ControlPoints[1] - ControlPoints[0]).Normalize();
XYZ dir2 = (ControlPoints[2] - ControlPoints[1]).Normalize();
m_corner1st = new WinderSinglePoint(ControlPoints[1], dir1, dir2, NumStepsInCorner1);
m_corner1st.Construct(RunWidth, CenterOffsetE1, CenterOffsetF1);
//
// Construct the second winder corner
//
XYZ dir3 = (ControlPoints[3] - ControlPoints[2]).Normalize();
m_corner2nd = new WinderSinglePoint(ControlPoints[1], dir2, dir3, NumStepsInCorner2);
m_corner2nd.Construct(RunWidth, CenterOffsetF2, CenterOffsetE2);
XYZ moveDelta = (m_corner1st.Distance2 + m_corner2nd.Distance1
+ TreadDepth * NumStepsInMiddle) * dir2;
m_corner2nd.Move(moveDelta);
//
// Construct the three straight runs
//
XYZ startPnt = m_corner1st.StartPoint - TreadDepth * NumStepsAtStart * dir1;
XYZ endPnt = m_corner2nd.EndPoint + TreadDepth * NumStepsAtEnd * dir3;
XYZ bisectDir = (dir2 - dir1).Normalize();
XYZ perpendicularDir1 = new XYZ(-dir1.Y, dir1.X, 0);
XYZ perpendicularDir2 = new XYZ(-dir2.Y, dir2.X, 0);
XYZ perpendicularDir3 = new XYZ(-dir3.Y, dir3.X, 0);
if (bisectDir.DotProduct(perpendicularDir1) < 0)
{
perpendicularDir1 = perpendicularDir1.Negate();
perpendicularDir2 = perpendicularDir2.Negate();
perpendicularDir3 = perpendicularDir3.Negate();
}
m_straightAtStart = new WinderStraight(
startPnt, m_corner1st.StartPoint, perpendicularDir1, NumStepsAtStart);
m_straightInMiddle = new WinderStraight(
m_corner1st.EndPoint, m_corner2nd.StartPoint, perpendicularDir2, NumStepsInMiddle);
m_straightAtEnd = new WinderStraight(
m_corner2nd.EndPoint, endPnt, perpendicularDir3, NumStepsAtEnd);
}
#endregion
/// <summary>
/// This method generates the sketch for U-shape winder stairs.
/// </summary>
protected override void GenerateSketch()
{
// Instantiate two winer corners and three straight runs.
Construct();
// Generate the sketch for two winder corners and three straight runs.
m_straightAtStart.GenerateSketch(
RunWidth, OuterBoundary, CenterWalkpath, InnerBoundary, RiserLines);
m_corner1st.GenerateSketch(
RunWidth, OuterBoundary, CenterWalkpath, InnerBoundary, RiserLines);
m_straightInMiddle.GenerateSketch(
RunWidth, OuterBoundary, CenterWalkpath, InnerBoundary, RiserLines);
m_corner2nd.GenerateSketch(
RunWidth, OuterBoundary, CenterWalkpath, InnerBoundary, RiserLines);
m_straightAtEnd.GenerateSketch(
RunWidth, OuterBoundary, CenterWalkpath, InnerBoundary, RiserLines);
}
}
}
@@ -0,0 +1,217 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
namespace Revit.SDK.Samples.WinderStairs.CS
{
/// <summary>
/// It represents a winder stairs, might include multiple straight runs and winder corners.
/// </summary>
abstract class Winder
{
/// <summary>
/// Control Points to determine the winder shape(e.g. L or U shape).
/// </summary>
public virtual IList<XYZ> ControlPoints { get; set; }
/// <summary>
/// Winder stairs Run width.
/// </summary>
public double RunWidth { get; set; }
/// <summary>
/// Winder stairs tread depth, it just makes sense for straight steps.
/// </summary>
public double TreadDepth { get; set; }
/// <summary>
/// Outer boundary curves calculated by algorithm.
/// </summary>
protected IList<Curve> OuterBoundary { get; private set; }
/// <summary>
/// Inner boundary curves calculated by algorithm.
/// </summary>
protected IList<Curve> InnerBoundary { get; private set; }
/// <summary>
/// Center walk-path calculated by algorithm.
/// </summary>
protected IList<Curve> CenterWalkpath { get; private set; }
/// <summary>
/// Riser lines calculated by algorithm.
/// </summary>
protected IList<Curve> RiserLines { get; set; }
/// <summary>
/// This method creates the sketched winder run and it also deletes the input winderRunId.
/// </summary>
/// <param name="rvtDoc">Revit Document to create the sketched run</param>
/// <param name="drawSketch">Flag to control whether to draw the sketch in document</param>
/// <param name="winderRunId">Previous created winder, it will be deleted</param>
public void Build(Document rvtDoc, bool drawSketch, ref ElementId winderRunId)
{
// Preparing the sketch containers.
OuterBoundary = new List<Curve>();
InnerBoundary = new List<Curve>();
CenterWalkpath = new List<Curve>();
RiserLines = new List<Curve>();
// Fill the sketch containers
GenerateSketch();
// Draw the sketch with model curves if required so.
if (drawSketch) DebugSketch(rvtDoc);
// Create the sketched run
CreateWinderRun(rvtDoc, ref winderRunId);
}
/// <summary>
/// This method generates the winder sketch and fills the sketch to the properties:
/// OuterBoundary, InnerBoundary, CenterWalkpath and RiserLines.
/// </summary>
protected abstract void GenerateSketch();
/// <summary>
/// This method creates the sketched run in Revit document.
/// </summary>
/// <param name="rvtDoc">Revit Document</param>
/// <param name="winderRunId">Created winder run</param>
private void CreateWinderRun(Document rvtDoc, ref ElementId winderRunId)
{
using (StairsEditScope stairsMode = new StairsEditScope(rvtDoc, GetType().Name))
{
var winderOldRun = rvtDoc.GetElement(winderRunId) as StairsRun;
var stairsId = ElementId.InvalidElementId;
// Non-existed stairs, create a new one.
if (winderOldRun == null)
{
// Find two levels to create a stairs between them
FilteredElementCollector filterLevels = new FilteredElementCollector(rvtDoc);
var levels = filterLevels.OfClass(typeof(Level)).ToElements();
List<Element> levelList = new List<Element>();
levelList.AddRange(levels);
levelList.Sort((a, b) =>
{ return ((Level)a).Elevation.CompareTo(((Level)b).Elevation); });
// Start the stairs edit mode
stairsId = stairsMode.Start(levelList[0].Id, levelList[1].Id);
}
else // using the existed stairs
{
// Start the stairs edit mode
stairsId = stairsMode.Start(winderOldRun.GetStairs().Id);
}
using (Transaction winderTransaction = new Transaction(rvtDoc))
{
// Start the winder creation transaction
winderTransaction.Start(GetType().Name);
// The boundaries is consist of internal and external boundaries.
List<Curve> boundarys = new List<Curve>();
boundarys.AddRange(InnerBoundary);
boundarys.AddRange(OuterBoundary);
// Calculate the run elevation.
Stairs stairs = rvtDoc.GetElement(stairsId) as Stairs;
double elevation = ControlPoints[0].Z;
double actualElevation = Math.Max(elevation, stairs.BaseElevation);
// Create the run
StairsRun run = StairsRun.CreateSketchedRun(rvtDoc, stairsId,
actualElevation, boundarys, RiserLines, CenterWalkpath);
if (ElementId.InvalidElementId != winderRunId)
{
// Delete the old run
rvtDoc.Delete(winderRunId);
}
// output the new run
winderRunId = run.Id;
// Finish the winder run creation.
winderTransaction.Commit();
}
// Finish the stairs Edit mode.
stairsMode.Commit(new StairsEditScopeFailuresPreprocessor());
}
}
/// <summary>
/// This method draws sketch as model curves in Revit document for debug purpose.
/// </summary>
/// <param name="rvtDoc">Revit document</param>
private void DebugSketch(Document rvtDoc)
{
try
{
using (Transaction debugTransaction = new Transaction(rvtDoc))
{
debugTransaction.Start("DEBUG API WINDER SKETCH");
SketchPlane skp = SketchPlane.Create(
rvtDoc, Plane.CreateByNormalAndOrigin(XYZ.BasisZ, ControlPoints[0]));
CurveArray curves = new CurveArray();
foreach (var curve in OuterBoundary)
{
curves.Append(curve);
}
foreach (var curve in InnerBoundary)
{
curves.Append(curve);
}
foreach (var curve in CenterWalkpath)
{
curves.Append(curve);
}
foreach (var curve in RiserLines)
{
curves.Append(curve);
}
rvtDoc.Create.NewModelCurveArray(curves, skp);
debugTransaction.Commit();
}
}
catch (System.Exception)
{
// SWALLOW ALL DEBUG EXCEPTION
}
}
}
class StairsEditScopeFailuresPreprocessor : IFailuresPreprocessor
{
public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
{
failuresAccessor.DeleteAllWarnings();
return FailureProcessingResult.Continue;
}
}
}
@@ -0,0 +1,123 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System.Collections.Generic;
using Autodesk.Revit.DB;
namespace Revit.SDK.Samples.WinderStairs.CS
{
/// <summary>
/// It represents a winder region used to connect straight runs. For L-shape stairs, there is
/// one WinderCorner, For U-shape stairs, there are two such components.
/// </summary>
abstract class WinderCorner
{
/*
* Direction1
* |
* |
* V
* |
* |
* |----->---- Direction2
* CornerPoint
*/
/// <summary>
/// Corner point of the winder region.
/// </summary>
public XYZ CornerPoint { get; private set; }
/// <summary>
/// The enter direction of the winder region.
/// </summary>
public XYZ Direction1 { get; private set; }
/// <summary>
/// The leave direction of the winder region.
/// </summary>
public XYZ Direction2 { get; private set; }
/// <summary>
/// Number of steps in the winder region.
/// </summary>
public uint NumSteps { get; private set; }
/// <summary>
/// The distance from start point to corner point.
/// </summary>
public double Distance1 { get; protected set; }
/// <summary>
/// The distance from corner point to end point.
/// </summary>
public double Distance2 { get; protected set; }
/// <summary>
/// Start delimiter of the winder region.
/// </summary>
public XYZ StartPoint { get { return CornerPoint - Direction1 * Distance1; } }
/// <summary>
/// End delimiter of the winder region.
/// </summary>
public XYZ EndPoint { get { return CornerPoint + Direction2 * Distance2; } }
/// <summary>
/// Constructor to initialize the basic fields of a winder region.
/// </summary>
/// <param name="cornerPnt">Corner Point</param>
/// <param name="dir1">Enter direction</param>
/// <param name="dir2">Leave direction</param>
/// <param name="steps">Number of steps</param>
protected WinderCorner(XYZ cornerPnt, XYZ dir1, XYZ dir2, uint steps)
{
CornerPoint = cornerPnt;
Direction1 = dir1;
Direction2 = dir2;
NumSteps = steps;
}
/// <summary>
/// Move the whole winder region by the given vector.
/// </summary>
/// <param name="vector">Move delta vector</param>
public virtual void Move(XYZ vector)
{
CornerPoint += vector;
}
/// <summary>
/// Generate the sketch in the winder region including the outer boundary, walk path,
/// inner boundary and riser lines. Subclass need to implement this method
/// to fill the input sketch using its winder layout algorithm.
/// </summary>
/// <param name="runWidth">Runwidth</param>
/// <param name="outerBoundary">Outer boundary</param>
/// <param name="walkPath">Walk path</param>
/// <param name="innerBoundary">Inner boundary</param>
/// <param name="riserLines">Riser lines</param>
public abstract void GenerateSketch(double runWidth,
IList<Curve> outerBoundary, IList<Curve> walkPath,
IList<Curve> innerBoundary, IList<Curve> riserLines);
}
}
@@ -0,0 +1,238 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
namespace Revit.SDK.Samples.WinderStairs.CS
{
/// <summary>
/// This represents a single point winder corner.
/// </summary>
class WinderSinglePoint : WinderCorner
{
/*
* Direction1
* |
* |
* V *(CenterPoint)
* |
* |
* |----->---- Direction2
* CornerPoint
*/
/// <summary>
/// Calculated point: All the riser lines are pass through this point.
/// </summary>
public XYZ CenterPoint { get; private set; }
/// <summary>
/// Constructor to initialize the basic fields of the winder region.
/// </summary>
/// <param name="cornerPnt">Corner Point</param>
/// <param name="dir1">Enter direction</param>
/// <param name="dir2">Leave direction</param>
/// <param name="steps">Number of steps</param>
public WinderSinglePoint(XYZ cornerPnt, XYZ dir1, XYZ dir2, uint steps)
: base(cornerPnt, dir1, dir2, steps)
{
}
/// <summary>
/// Calculate the CenterPoint base on Australia single-point layout algorithm.
/// </summary>
/// <param name="runWidth">Stairs Runwidth</param>
/// <param name="offset1">CenterPoint Offset from the first inner boundary</param>
/// <param name="offset2">CenterPoint Offset from the second inner boundary</param>
public void Construct(double runWidth, double offset1, double offset2)
{
XYZ bisectDir = (Direction2 - Direction1).Normalize();
XYZ perpendicularDir1 = new XYZ(-Direction1.Y, Direction1.X, 0);
XYZ perpendicularDir2 = new XYZ(-Direction2.Y, Direction2.X, 0);
if (bisectDir.DotProduct(perpendicularDir1) < 0)
{
perpendicularDir1 = perpendicularDir1.Negate();
perpendicularDir2 = perpendicularDir2.Negate();
}
Line line1Offset = Line.CreateUnbound(
CornerPoint + perpendicularDir1 * (runWidth + offset1), Direction1);
Line line2Offset = Line.CreateUnbound(
CornerPoint + perpendicularDir2 * (runWidth + offset2), Direction2);
IntersectionResultArray xsect;
line1Offset.Intersect(line2Offset, out xsect);
CenterPoint = xsect.get_Item(0).XYZPoint;
Line line1 = Line.CreateUnbound(CornerPoint, Direction1.Negate());
Line line2 = Line.CreateUnbound(CornerPoint, Direction2);
var proj1 = line1.Project(CenterPoint);
var proj2 = line2.Project(CenterPoint);
Distance1 = proj1.Parameter;
Distance2 = proj2.Parameter;
}
/// <summary>
/// Generate the sketch base on the calculated CenterPoint:
/// Divide the corner into NumSteps evenly.
/// </summary>
public override void GenerateSketch(double runWidth,
IList<Curve> outerBoundary, IList<Curve> walkPath,
IList<Curve> innerBoundary, IList<Curve> riserLines)
{
// Calculate the bisect direction in the corner.
XYZ bisectDir = (Direction2 - Direction1).Normalize();
XYZ perpendicularDir1 = new XYZ(-Direction1.Y, Direction1.X, 0);
XYZ perpendicularDir2 = new XYZ(-Direction2.Y, Direction2.X, 0);
if (bisectDir.DotProduct(perpendicularDir1) < 0)
{
perpendicularDir1 = perpendicularDir1.Negate();
perpendicularDir2 = perpendicularDir2.Negate();
}
// Determine the rotation axis and the angle span in the corner.
double runwidth_2 = runWidth * 0.5;
XYZ zDir = XYZ.BasisZ;
double winderAngleSpan = perpendicularDir1.AngleOnPlaneTo(perpendicularDir2, zDir);
if (winderAngleSpan > Math.PI)
{
zDir = zDir.Negate();
winderAngleSpan = Math.PI * 2.0 - winderAngleSpan;
}
// Calculate the corner points
double diagonalDist = runwidth_2 / Math.Cos(winderAngleSpan * 0.5);
XYZ middleCornerPnt = CornerPoint + bisectDir * diagonalDist;
XYZ innerCornerPnt = middleCornerPnt + bisectDir * diagonalDist;
XYZ middleStart = StartPoint + perpendicularDir1 * runwidth_2;
XYZ innerStart = StartPoint + perpendicularDir1 * runWidth;
XYZ middleEnd = EndPoint + perpendicularDir2 * runwidth_2;
XYZ innerEnd = EndPoint + perpendicularDir2 * runWidth;
XYZ middleEnd0 = innerCornerPnt - perpendicularDir1 * runwidth_2;
XYZ middleEnd1 = innerCornerPnt - perpendicularDir2 * runwidth_2;
// Generate the two outer boundary lines
Line outerLine1 = Line.CreateBound(StartPoint, CornerPoint);
outerBoundary.Add(outerLine1);
Line outerLine2 = Line.CreateBound(CornerPoint, EndPoint);
outerBoundary.Add(outerLine2);
// Generate the first inner line
Line innerLine1 = null;
if (!innerStart.IsAlmostEqualTo(innerCornerPnt))
{
innerLine1 = Line.CreateBound(innerStart, innerCornerPnt);
innerBoundary.Add(innerLine1);
}
// Generate the second inner line
Line innerLine2 = null;
if (!innerCornerPnt.IsAlmostEqualTo(innerEnd))
{
innerLine2 = Line.CreateBound(innerCornerPnt, innerEnd);
innerBoundary.Add(innerLine2);
}
// Generate the first middle line
Line middleLine1 = null;
if (!middleStart.IsAlmostEqualTo(middleEnd0))
{
middleLine1 = Line.CreateBound(middleStart, middleEnd0);
walkPath.Add(middleLine1);
}
// Generate the middle fillet arc
XYZ middleCenter = innerCornerPnt - bisectDir * runwidth_2;
Arc middleArc = Arc.Create(middleEnd0, middleEnd1, middleCenter);
walkPath.Add(middleArc);
// Genera the second middle line
Line middleLine2 = null;
if (!middleEnd1.IsAlmostEqualTo(middleEnd))
{
middleLine2 = Line.CreateBound(middleEnd1, middleEnd);
walkPath.Add(middleLine2);
}
//
// Generate the riser lines by dividing the corner into NumSteps evenly.
//
double winderAnglePerStep = winderAngleSpan / NumSteps;
Transform tsf = Transform.CreateRotation(zDir, winderAnglePerStep);
XYZ currentDir = perpendicularDir1;
for (int i = 0; i < NumSteps - 1; ++i)
{
XYZ rayDir = tsf.OfVector(currentDir); currentDir = rayDir;
Line ray = Line.CreateUnbound(CenterPoint, rayDir);
IntersectionResultArray xsect;
if (ray.Intersect(outerLine1, out xsect) == SetComparisonResult.Overlap ||
ray.Intersect(outerLine2, out xsect) == SetComparisonResult.Overlap)
{
XYZ xOuter = xsect.get_Item(0).XYZPoint;
XYZ xInner = null;
if (innerLine1 == null || innerLine2 == null)
{
if (ray.Distance(innerCornerPnt) < 1.0e-9)
{
xInner = innerCornerPnt;
}
}
if (xInner == null)
{
if (innerLine1 != null && ray.Intersect(innerLine1, out xsect) == SetComparisonResult.Overlap)
{
xInner = xsect.get_Item(0).XYZPoint;
}
else if (innerLine2 != null && ray.Intersect(innerLine2, out xsect) == SetComparisonResult.Overlap)
{
xInner = xsect.get_Item(0).XYZPoint;
}
}
if (xInner == null)
{
throw new ArgumentException("Bad Input.");
}
riserLines.Add(Line.CreateBound(xOuter, xInner));
}
else
{
throw new ArgumentException("Bad Input.");
}
}
}
/// <summary>
/// Move the center point
/// </summary>
public override void Move(XYZ vector)
{
base.Move(vector);
CenterPoint += vector;
}
}
}
@@ -0,0 +1,127 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System.Collections.Generic;
using Autodesk.Revit.DB;
namespace Revit.SDK.Samples.WinderStairs.CS
{
/// <summary>
/// It represents a straight run connected to winder-corner.
/// </summary>
class WinderStraight
{
/*
* (StartPoint)-------->--------(EndPoint)
* |
* |
* V (OffsetDirection)
* |
* |
* -----------------
*
*/
/// <summary>
/// Start delimiter of the straight run.
/// </summary>
public XYZ StartPoint { get; private set; }
/// <summary>
/// End delimiter of the straight run.
/// </summary>
public XYZ EndPoint { get; private set; }
/// <summary>
/// Perpendicular direction of start-to-end direction.
/// </summary>
public XYZ OffsetDirection { get; private set; }
/// <summary>
/// Number of steps in this straight run.
/// </summary>
public uint NumSteps { get; private set; }
/// <summary>
/// Constructor to initialize the basic fields of the straight run.
/// </summary>
/// <param name="start">Start point</param>
/// <param name="end">End point</param>
/// <param name="offsetDir">Offset direction</param>
/// <param name="numSteps">Number of steps</param>
public WinderStraight(XYZ start, XYZ end, XYZ offsetDir, uint numSteps)
{
StartPoint = start;
EndPoint = end;
NumSteps = numSteps;
OffsetDirection = offsetDir;
}
/// <summary>
/// Generate sketch of the straight run.
/// </summary>
public void GenerateSketch(double runWidth,
IList<Curve> outerBoundary, IList<Curve> walkPath,
IList<Curve> innerBoundary, IList<Curve> riserLines)
{
if (NumSteps == 0)
{
// Just Generate one riser line.
XYZ middleOffset = StartPoint + OffsetDirection * runWidth * 0.5;
XYZ xOuter = middleOffset - OffsetDirection * runWidth * 0.5;
XYZ xInner = middleOffset + OffsetDirection * runWidth * 0.5;
riserLines.Add(Line.CreateBound(xOuter, xInner));
return;
}
// For NumSteps > 0:
//
// Generate the outer boundary line.
double runwidth_2 = runWidth * 0.5;
Line outBounary = Line.CreateBound(StartPoint, EndPoint);
outerBoundary.Add(outBounary);
// Generate the middle walk path line.
XYZ middleStart = StartPoint + OffsetDirection * runWidth * 0.5;
XYZ middleEnd = EndPoint + OffsetDirection * runwidth_2;
walkPath.Add(Line.CreateBound(middleStart, middleEnd));
// Generate the inner boundary line.
XYZ innerStart = StartPoint + OffsetDirection * runWidth;
XYZ innerEnd = EndPoint + OffsetDirection * runWidth;
innerBoundary.Add(Line.CreateBound(innerStart, innerEnd));
// Generate the NumSteps+1 riser lines.
double treadDepth = StartPoint.DistanceTo(EndPoint) / (double)NumSteps;
XYZ dir = (EndPoint - StartPoint).Normalize();
XYZ currentStep = StartPoint + OffsetDirection * runWidth * 0.5;
XYZ deltaStep = dir * treadDepth;
for (int i = 0; i <= NumSteps; i++)
{
XYZ xOuter = currentStep - OffsetDirection * runwidth_2;
XYZ xInner = currentStep + OffsetDirection * runwidth_2;
riserLines.Add(Line.CreateBound(xOuter, xInner));
currentStep = currentStep + deltaStep;
}
}
}
}
@@ -0,0 +1,302 @@
//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
namespace Revit.SDK.Samples.WinderStairs.CS
{
/// <summary>
/// Utility verifies the input parameters, like curves from Revit document.
/// It also adapts the input data for winder stairs creation.
/// </summary>
class WinderUtil
{
/// <summary>
/// Return the control points from the connected curve elements.
/// </summary>
/// <param name="rvtDoc">Revit Document</param>
/// <param name="crvElements">Connected curve element</param>
/// <returns>Control points</returns>
public static IList<XYZ> CalculateControlPoints(Document rvtDoc, IList<ElementId> crvElements)
{
double maxOffset = 0.0;
// All the elements should be line base.
for (int i = 0; i < crvElements.Count; i++)
{
Element curve = rvtDoc.GetElement(crvElements[i]);
LocationCurve locationCrv = curve.Location as LocationCurve;
if (locationCrv == null || !(locationCrv.Curve is Line))
{
throw new ArgumentException("The input elements are not Line base.");
}
if (Math.Abs(locationCrv.Curve.GetEndPoint(0).Z
- locationCrv.Curve.GetEndPoint(1).Z) > 1.0e-9)
{
throw new AggregateException(
"The input curve elements are not in the same elevation plane.");
}
if (curve is Wall)
{
maxOffset = Math.Max(maxOffset, ((Wall)curve).Width * 0.5);
}
}
IList<XYZ> controlPoints = CalculateControlPoints2(rvtDoc, crvElements);
if (controlPoints.Count == 0)
{
throw new ArgumentException("The input curve elements are not continues.");
}
if (!CheckOrientation(controlPoints))
{
throw new ArgumentException(
"The input curve elements should have the same orientation: CW or CCW.");
}
if (maxOffset > 0.0)
{
controlPoints = CalculateOffset(controlPoints, maxOffset);
}
return controlPoints;
}
/// <summary>
/// Calculate the max straight steps determined by the control points.
/// </summary>
/// <param name="controlPoints">Control points of the stairs</param>
/// <param name="runWidth">Stairs Run width</param>
/// <param name="treadDepth">Stairs tread depth</param>
/// <returns></returns>
public static IList<uint> CalculateMaxStepsCount(IList<XYZ> controlPoints,
double runWidth, double treadDepth)
{
IList<XYZ> innerPnts = CalculateOffset(controlPoints, runWidth);
IList<uint> counts = new List<uint>();
for (int i = 1; i < innerPnts.Count; i++)
{
double dist = innerPnts[i].DistanceTo(innerPnts[i - 1]);
uint count = (uint)(dist / treadDepth);
counts.Add(count);
}
return counts;
}
/// <summary>
/// Check to see if the control points bend to the same direction(CW or CCW).
/// </summary>
/// <param name="controlPoints">Control points to test</param>
/// <returns>true if the controls points bend to the same direction</returns>
static bool CheckOrientation(IList<XYZ> controlPoints)
{
XYZ previousDir = null;
for (int i = 1; i < controlPoints.Count - 1; i++)
{
XYZ dir1 = controlPoints[i] - controlPoints[i - 1];
XYZ dir2 = controlPoints[i + 1] - controlPoints[i];
if (previousDir == null)
{
previousDir = dir1.CrossProduct(dir2).Normalize();
}
else if (!previousDir.IsAlmostEqualTo(dir1.CrossProduct(dir2).Normalize()))
{
return false;
}
}
return true;
}
/// <summary>
/// Offset the control points by specified distance.
/// </summary>
/// <param name="controlPoints">Control point to offset</param>
/// <param name="offset">offset distance</param>
/// <returns>Control points after offsetting</returns>
static IList<XYZ> CalculateOffset(IList<XYZ> controlPoints, double offset)
{
IList<XYZ> innerPnts = new List<XYZ>();
for (int i = 1; i < controlPoints.Count - 1; i++)
{
XYZ dir1 = (controlPoints[i] - controlPoints[i - 1]).Normalize();
XYZ dir2 = (controlPoints[i + 1] - controlPoints[i]).Normalize();
// Calculate the bisect direction of the corner.
XYZ bisectDir = (dir2 - dir1).Normalize();
// Calculate the step direction of the fist line.
XYZ stepInside1stDir = new XYZ(-dir1.Y, dir1.X, 0.0);
if (stepInside1stDir.DotProduct(bisectDir) < 0.0)
stepInside1stDir = stepInside1stDir.Negate();
if (i == 1)
{
innerPnts.Add(controlPoints[i - 1] + stepInside1stDir * offset);
}
// Calculate the step direction of the second line.
XYZ stepInside2ndDir = new XYZ(-dir2.Y, dir2.X, 0.0);
if (stepInside2ndDir.DotProduct(bisectDir) < 0.0)
stepInside2ndDir = stepInside2ndDir.Negate();
double semiAngle = bisectDir.AngleTo(dir2);
double slopDist = offset / Math.Sin(semiAngle);
// Calculate the corner points
XYZ innerCornerPnt = controlPoints[i] + bisectDir * slopDist;
innerPnts.Add(innerCornerPnt);
if (i == controlPoints.Count - 2)
{
innerPnts.Add(controlPoints[i + 1] + stepInside2ndDir * offset);
}
}
return innerPnts;
}
/// <summary>
/// Calculate the control points from the connected curve elements.
/// </summary>
/// <param name="rvtDoc">Revit Document</param>
/// <param name="elements">Connected Curve Elements</param>
/// <returns>Control points</returns>
static IList<XYZ> CalculateControlPoints2(Document rvtDoc, IList<ElementId> elements)
{
IList<Curve> curves = new List<Curve>();
for (int i = 0; i < elements.Count; i++)
{
Element curve = rvtDoc.GetElement(elements[i]);
LocationCurve locationCrv = curve.Location as LocationCurve;
curves.Add(locationCrv.Curve);
}
IList<XYZ> controlPoints = new List<XYZ>();
if (curves.Count == 2)
{
Curve curve1 = curves[0];
Curve curve2 = curves[1];
XYZ commonPnt = null;
int index1 = -1, index2 = -1;
if (HasCommonEndPoint(curve1, curve2, out commonPnt, out index1, out index2))
{
XYZ start = curve1.GetEndPoint(1 - index1);
XYZ end = curve2.GetEndPoint(1 - index2);
controlPoints.Add(start);
controlPoints.Add(commonPnt);
controlPoints.Add(end);
}
}
else if (curves.Count == 3)
{
Curve curve1 = curves[0];
Curve curve2 = curves[1];
Curve curve3 = curves[2];
XYZ start = null, commonPnt1 = null, commonPnt2 = null, end = null;
int index1 = -1, index2 = -1, index3 = -1, index4 = -1;
if (HasCommonEndPoint(curve1, curve2, out commonPnt1, out index1, out index2))
{
if (HasCommonEndPoint(curve1, curve3, out commonPnt2, out index3, out index4))
{
// common curve is curve1
start = curve2.GetEndPoint(1 - index2);
end = curve3.GetEndPoint(1 - index4);
}
else if (HasCommonEndPoint(curve2, curve3, out commonPnt2, out index3, out index4))
{
// common curve is curve2
start = curve1.GetEndPoint(1 - index1);
end = curve3.GetEndPoint(1 - index4);
}
}
else
{
if (HasCommonEndPoint(curve1, curve3, out commonPnt1, out index1, out index2) &&
HasCommonEndPoint(curve2, curve3, out commonPnt2, out index3, out index4))
{
// common curve is curve3
start = curve1.GetEndPoint(1 - index1);
end = curve2.GetEndPoint(1 - index3);
}
}
if (start != null)
{
controlPoints.Add(start);
controlPoints.Add(commonPnt1);
controlPoints.Add(commonPnt2);
controlPoints.Add(end);
}
}
return controlPoints;
}
/// <summary>
/// Calculate the common end point of two curves.
/// </summary>
/// <param name="crv1">Curve 1</param>
/// <param name="crv2">Curve 2</param>
/// <param name="common">Comment point of the two curves</param>
/// <param name="index1">index of the common point in curve 1</param>
/// <param name="index2">index of the common point in curve 2</param>
/// <returns>true if there is one common point, false otherwise</returns>
static bool HasCommonEndPoint(Curve crv1, Curve crv2, out XYZ common,
out int index1, out int index2)
{
XYZ pnt1 = crv1.GetEndPoint(0);
XYZ pnt2 = crv1.GetEndPoint(1);
XYZ pnt3 = crv2.GetEndPoint(0);
XYZ pnt4 = crv2.GetEndPoint(1);
if (pnt1.IsAlmostEqualTo(pnt3))
{
index1 = 0; index2 = 0;
common = pnt1;
return true;
}
else if (pnt1.IsAlmostEqualTo(pnt4))
{
index1 = 0; index2 = 1;
common = pnt1;
return true;
}
else if (pnt2.IsAlmostEqualTo(pnt3))
{
index1 = 1; index2 = 0;
common = pnt2;
return true;
}
else if (pnt2.IsAlmostEqualTo(pnt4))
{
index1 = 1; index2 = 1;
common = pnt2;
return true;
}
common = null;
index1 = index2 = -1;
return false;
}
}
}