// // (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 System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using Autodesk.Revit; using System.Collections; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using System.Drawing.Drawing2D; namespace Revit.SDK.Samples.SlabShapeEditing.CS { /// /// window form contains one picture box to show the /// profile of slab geometry. user can add vertex and crease. /// User can edit slab shape via vertex and crease too. /// public partial class SlabShapeEditingForm : System.Windows.Forms.Form { enum EditorState { AddVertex, AddCrease, Select, Rotate, Null }; ExternalCommandData m_commandData; //object which contains reference of Revit Application SlabProfile m_slabProfile; //store geometry info of selected slab PointF m_mouseRightDownLocation; //where mouse right button down LineTool m_lineTool; //tool use to draw crease LineTool m_pointTool; //tool use to draw vertex ArrayList m_graphicsPaths; //store all the GraphicsPath objects of crease and vertex. int m_selectIndex; //index of crease and vertex which mouse hovering on. int m_clickedIndex; //index of crease and vertex which mouse clicked. ArrayList m_createdVertices; // new created vertices ArrayList m_createCreases; // new created creases private SlabShapeEditor m_slabShapeEditor; //object use to edit slab shape SlabShapeCrease m_selectedCrease; //selected crease, mouse clicked on SlabShapeVertex m_selectedVertex; //selected vertex, mouse clicked on EditorState editorState; //state of user's operation Pen m_toolPen; //pen use to draw new created vertex and crease Pen m_selectPen; // pen use to draw vertex and crease which been selected Pen m_profilePen; // pen use to draw slab's profile const string justNumber = "Please input numbers in textbox!"; //error message const string selectFirst = "Please select a Vertex (or Crease) first!"; //error message /// /// constructor /// /// selected floor (or slab) /// contains reference of Revit Application public SlabShapeEditingForm(Floor floor, ExternalCommandData commandData) { InitializeComponent(); m_commandData = commandData; m_slabProfile = new SlabProfile(floor, commandData); m_slabShapeEditor = floor.GetSlabShapeEditor(); m_lineTool = new LineTool(); m_pointTool = new LineTool(); editorState = EditorState.AddVertex; m_graphicsPaths = new ArrayList(); m_createdVertices = new ArrayList(); m_createCreases = new ArrayList(); m_selectIndex = -1; m_clickedIndex = -1; m_toolPen = new Pen(System.Drawing.Color.Blue, 2); m_selectPen = new Pen(System.Drawing.Color.Red, 2); m_profilePen = new Pen(System.Drawing.Color.Black, (float)(0.5)); } /// /// represents the geometry info for slab /// /// object who sent this event /// event args private void SlabShapePictureBox_Paint(object sender, PaintEventArgs e) { e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; m_slabProfile.Draw2D(e.Graphics, m_profilePen); if (EditorState.Rotate != editorState) { m_lineTool.Draw2D(e.Graphics, m_toolPen); m_pointTool.DrawRectangle(e.Graphics, m_toolPen); //draw selected beam (line) by red pen DrawSelectedLineRed(e.Graphics, m_selectPen); } } /// /// Draw selected crease or vertex red /// /// Form graphics object, /// Pen which used to draw lines private void DrawSelectedLineRed(Graphics graphics, Pen pen) { if (-1 != m_selectIndex) { GraphicsPath selectedPath = (GraphicsPath)m_graphicsPaths[m_selectIndex]; PointF pointF0 = (PointF)selectedPath.PathPoints.GetValue(0); PointF pointF1 = (PointF)selectedPath.PathPoints.GetValue(1); if (m_selectIndex < m_createCreases.Count) { graphics.DrawLine(pen, pointF0, pointF1); } else { graphics.DrawRectangle(pen, pointF0.X - 2, pointF0.Y - 2, 4, 4); } } if (-1 != m_clickedIndex) { GraphicsPath clickedPath = (GraphicsPath)m_graphicsPaths[m_clickedIndex]; PointF pointF0 = (PointF)clickedPath.PathPoints.GetValue(0); PointF pointF1 = (PointF)clickedPath.PathPoints.GetValue(1); if (m_clickedIndex < m_createCreases.Count) { graphics.DrawLine(pen, pointF0, pointF1); } else { graphics.DrawRectangle(pen, pointF0.X - 2, pointF0.Y - 2, 4, 4); } } } /// /// rotate slab and get selected vertex or crease /// /// object who sent this event /// event args private void SlabShapePictureBox_MouseMove(object sender, MouseEventArgs e) { PointF pointF = new PointF(e.X, e.Y); if (EditorState.AddCrease == editorState && 1 == m_lineTool.Points.Count % 2) { m_lineTool.MovePoint = pointF; } else { m_lineTool.MovePoint = PointF.Empty; } if (MouseButtons.Right == e.Button) { double moveX = e.Location.X - m_mouseRightDownLocation.X; double moveY = m_mouseRightDownLocation.Y - e.Location.Y; m_slabProfile.RotateFloor(moveY / 500, moveX / 500); m_mouseRightDownLocation = e.Location; } else if (EditorState.Select == editorState) { for (int i = 0; i < m_graphicsPaths.Count; i++) { GraphicsPath path = (GraphicsPath)m_graphicsPaths[i]; if (path.IsOutlineVisible(pointF, m_toolPen)) { m_selectIndex = i; break; } m_selectIndex = -1; } } this.SlabShapePictureBox.Refresh(); } /// /// get location where right button click down. /// /// object who sent this event /// event args private void SlabShapePictureBox_MouseDown(object sender, MouseEventArgs e) { if (MouseButtons.Right == e.Button) { m_mouseRightDownLocation = e.Location; editorState = EditorState.Rotate; m_clickedIndex = m_selectIndex = -1; } } /// /// add vertex and crease, select new created vertex and crease /// /// object who sent this event /// event args private void SlabShapePictureBox_MouseClick(object sender, MouseEventArgs e) { if (EditorState.AddCrease == editorState) { if (!m_slabProfile.CanCreateVertex(new PointF(e.X, e.Y))) { return; } m_lineTool.Points.Add(new PointF(e.X, e.Y)); int lineSize = m_lineTool.Points.Count; if (0 == m_lineTool.Points.Count % 2) { m_createCreases.Add( m_slabProfile.AddCrease((PointF)m_lineTool.Points[lineSize - 2], (PointF)m_lineTool.Points[lineSize - 1])); } CreateGraphicsPath(); //create graphic path for all the vertex and crease } else if (EditorState.AddVertex == editorState) { SlabShapeVertex vertex = m_slabProfile.AddVertex(new PointF(e.X, e.Y)); if (null == vertex) { return; } m_pointTool.Points.Add(new PointF(e.X, e.Y)); //draw point as a short line, so add two points here m_pointTool.Points.Add(new PointF((float)(e.X + 2), (float)(e.Y + 2))); m_createdVertices.Add(vertex); CreateGraphicsPath(); //create graphic path for all the vertex and crease } else if (EditorState.Select == editorState) { if (m_selectIndex >= 0) { m_clickedIndex = m_selectIndex; if (m_selectIndex <= m_createCreases.Count - 1) { m_selectedCrease = (SlabShapeCrease)(m_createCreases[m_selectIndex]); m_selectedVertex = null; } else { //put all path (crease and vertex) in one arrayList, so reduce creases.count int index = m_selectIndex - m_createCreases.Count; m_selectedVertex = (SlabShapeVertex)(m_createdVertices[index]); m_selectedCrease = null; } } else { m_selectedVertex = null; m_selectedCrease = null; m_clickedIndex = -1; } } this.SlabShapePictureBox.Refresh(); } /// /// get ready to add vertex /// /// object who sent this event /// event args private void PointButton_Click(object sender, EventArgs e) { editorState = EditorState.AddVertex; m_slabProfile.ClearRotateMatrix(); this.SlabShapePictureBox.Cursor = Cursors.Cross; } /// /// get ready to add crease /// /// object who sent this event /// event args private void LineButton_Click(object sender, EventArgs e) { editorState = EditorState.AddCrease; m_slabProfile.ClearRotateMatrix(); this.SlabShapePictureBox.Cursor = Cursors.Cross; } /// /// get ready to move vertex and crease /// /// object who sent this event /// event args private void MoveButton_Click(object sender, EventArgs e) { editorState = EditorState.Select; m_slabProfile.ClearRotateMatrix(); this.SlabShapePictureBox.Cursor = Cursors.Arrow; } /// /// Move vertex and crease, then update profile of slab /// /// object who sent this event /// event args private void UpdateButton_Click(object sender, EventArgs e) { if (-1 == m_clickedIndex) { Autodesk.Revit.UI.TaskDialog.Show("Revit", selectFirst); return; } double moveDistance = 0; try { moveDistance = Convert.ToDouble(this.DistanceTextBox.Text); } catch (Exception) { Autodesk.Revit.UI.TaskDialog.Show("Revit", justNumber); return; } using (Transaction transaction = new Transaction( m_commandData.Application.ActiveUIDocument.Document, "Update")) { transaction.Start(); if (null != m_selectedCrease) { m_slabShapeEditor.ModifySubElement(m_selectedCrease, moveDistance); } else if (null != m_selectedVertex) { m_slabShapeEditor.ModifySubElement(m_selectedVertex, moveDistance); } transaction.Commit(); } //re-calculate geometry info m_slabProfile.GetSlabProfileInfo(); this.SlabShapePictureBox.Refresh(); } /// /// Reset slab shape /// /// object who sent this event /// event args private void ResetButton_Click(object sender, EventArgs e) { m_slabProfile.ResetSlabShape(); m_lineTool.Points.Clear(); m_pointTool.Points.Clear(); } /// /// Create Graphics Path for each vertex and crease /// public void CreateGraphicsPath() { m_graphicsPaths.Clear(); //create path for all the lines draw by user for (int i = 0; i < m_lineTool.Points.Count - 1; i += 2) { GraphicsPath path = new GraphicsPath(); path.AddLine((PointF)m_lineTool.Points[i], (PointF)m_lineTool.Points[i + 1]); m_graphicsPaths.Add(path); } for (int i = 0; i < m_pointTool.Points.Count - 1; i += 2) { GraphicsPath path = new GraphicsPath(); path.AddLine((PointF)m_pointTool.Points[i], (PointF)m_pointTool.Points[i + 1]); m_graphicsPaths.Add(path); } } /// /// set tool tip for MoveButton /// /// object who sent this event /// event args private void MoveButton_MouseHover(object sender, EventArgs e) { this.toolTip.SetToolTip(this.MoveButton, "Select Vertex or Crease"); } /// /// set tool tip for PointButton /// /// object who sent this event /// event args private void PointButton_MouseHover(object sender, EventArgs e) { this.toolTip.SetToolTip(this.PointButton, "Add Vertex"); } /// /// set tool tip for LineButton /// /// object who sent this event /// event args private void LineButton_MouseHover(object sender, EventArgs e) { this.toolTip.SetToolTip(this.LineButton, "Add Crease"); } /// /// change cursor /// /// object who sent this event /// event args private void SlabShapePictureBox_MouseHover(object sender, EventArgs e) { switch (editorState) { case EditorState.AddVertex: this.SlabShapePictureBox.Cursor = Cursors.Cross; break; case EditorState.AddCrease: this.SlabShapePictureBox.Cursor = Cursors.Cross; break; case EditorState.Select: this.SlabShapePictureBox.Cursor = Cursors.Arrow; break; default: this.SlabShapePictureBox.Cursor = Cursors.Default; break; } } } }