/// <summary> /// copy constructor, initialize the curtain grid line with another grid line 2D /// </summary> /// <param name="gridLine2D"> /// the source line /// </param> public GridLine2D(GridLine2D gridLine2D) : base((Line2D)gridLine2D) { m_segments = new List <SegmentLine2D>(); m_locked = gridLine2D.Locked; m_removedNumber = gridLine2D.RemovedNumber; m_isUGridLine = gridLine2D.IsUGridLine; foreach (SegmentLine2D segLine in gridLine2D.Segments) { m_segments.Add(new SegmentLine2D(segLine)); } }
/// <summary> /// a simulative "Delete Segment" operation before real deletion /// as we may occur some situations that prevent us to delete the specific segment /// for example, delete the specific segment will make some other segments to be deleted automatically (the "conjoint" ones) /// and the "automatically deleted" segment is the last segment of its parent grid line /// in this situation, we should prevent deleting that specific segment and rollback all the simulative deletion /// </summary> /// <param name="removeList"> /// the refferred to-be-removed list, in the simulative deletion operation, all the suitable (not the last segment) segments will /// be added to that list /// </param> private void MimicRemoveSegments(ref bool canRemove, List <SegmentLine2D> removeList) { // the currently operated is a U segment if (-1 != m_drawing.SelectedUIndex) { GridLine2D gridLine2D = m_drawing.UGridLines2D[m_drawing.SelectedUIndex]; SegmentLine2D segLine2D = gridLine2D.Segments[m_drawing.SelectedUSegmentIndex]; // the to-be-deleted segment is the last one of the grid line, it's not allowed to delete it int existingNumber = gridLine2D.Segments.Count - gridLine2D.RemovedNumber; if (1 == existingNumber) { canRemove = false; return; } // simulative deletion gridLine2D.RemovedNumber++; segLine2D.Removed = true; gridLine2D.Segments[m_drawing.SelectedUSegmentIndex] = segLine2D; removeList.Add(segLine2D); // the "regeneration" step: if there're only 2 segments existing in one joint and they're in the same line, delete one seg will cause the other // been deleted automatically MimicRecursiveDelete(ref canRemove, segLine2D, removeList); } // the currently operated is a V segment else if (-1 != m_drawing.SelectedVIndex) { GridLine2D gridLine2D = m_drawing.VGridLines2D[m_drawing.SelectedVIndex]; SegmentLine2D segLine2D = gridLine2D.Segments[m_drawing.SelectedVSegmentIndex]; int existingNumber = gridLine2D.Segments.Count - gridLine2D.RemovedNumber; // the to-be-deleted segment is the last one of the grid line, it's not allowed to delete it if (1 == existingNumber) { canRemove = false; return; } // simulative deletion gridLine2D.RemovedNumber++; segLine2D.Removed = true; gridLine2D.Segments[m_drawing.SelectedVSegmentIndex] = segLine2D; removeList.Add(segLine2D); // the "regeneration" step: if there're only 2 segments existing in one joint and they're in the same line, delete one seg will cause the other // been deleted automatically MimicRecursiveDelete(ref canRemove, segLine2D, removeList); } }
/// <summary> /// toggle the selected grid line's Lock status: if it's locked, unlock it, vice versa /// </summary> public void LockOrUnlockSelectedGridLine() { CurtainGridLine line = null; GridLine2D line2D = new GridLine2D(); // get the selected grid line if (-1 != m_drawing.SelectedUIndex) { line = m_uGridLines[m_drawing.SelectedUIndex]; line2D = m_drawing.UGridLines2D[m_drawing.SelectedUIndex]; } else if (-1 != m_drawing.SelectedVIndex) { line = m_vGridLines[m_drawing.SelectedVIndex]; line2D = m_drawing.VGridLines2D[m_drawing.SelectedVIndex]; } else { return; } // lock/unlock the grid line if (null != line) { Transaction act = new Transaction(m_activeDocument, Guid.NewGuid().GetHashCode().ToString()); act.Start(); line.Lock = !line.Lock; act.Commit(); } // update the mapped line2D's data line2D.Locked = line.Lock; // clear the intermediate variables and instances m_drawing.DrawObject.Clear(); }
/// <summary> /// copy constructor, initialize the curtain grid line with another grid line 2D /// </summary> /// <param name="gridLine2D"> /// the source line /// </param> public GridLine2D(GridLine2D gridLine2D) : base((Line2D)gridLine2D) { m_segments = new List<SegmentLine2D>(); m_locked = gridLine2D.Locked; m_removedNumber = gridLine2D.RemovedNumber; m_isUGridLine = gridLine2D.IsUGridLine; foreach (SegmentLine2D segLine in gridLine2D.Segments) { m_segments.Add(new SegmentLine2D(segLine)); } }
/// <summary> /// move the selected grid line to the location of the mouse cursor /// </summary> /// <param name="mousePosition"> /// indicates the destination position of the grid line /// </param> /// <returns> /// return whether the grid line be moved successfully /// </returns> public bool MoveGridLine(System.Drawing.Point mousePosition) { // verify that the mouse location is valid: it's inside the curtain grid area // & it doesn't lap over another grid line (it's not allowed to move a grid line to lap over another one) if (false == m_drawing.MouseLocationValid) { return(false); } if (null == m_lineToBeMoved) { return(false); } // move a U line along the V direction if (-1 != m_drawing.SelectedUIndex) { // convert the 2D data to 3D Autodesk.Revit.DB.XYZ xyz = new Autodesk.Revit.DB.XYZ(mousePosition.X, mousePosition.Y, 0); Vector4 vec = new Vector4(xyz); vec = m_drawing.Coordinates.RestoreMatrix.Transform(vec); double offset = vec.Z - m_lineToBeMoved.FullCurve.GetEndPoint(0).Z; xyz = new Autodesk.Revit.DB.XYZ(0, 0, offset); Transaction act = new Transaction(m_activeDocument, Guid.NewGuid().GetHashCode().ToString()); act.Start(); try { ElementTransformUtils.MoveElement(m_activeDocument, m_lineToBeMoved.Id, xyz); } catch (System.Exception e) { TaskDialog.Show("Exception", e.Message); return(false); } act.Commit(); // update the grid line 2d GridLine2D line = m_drawing.UGridLines2D[m_drawing.SelectedUIndex]; line.StartPoint = new System.Drawing.Point(line.StartPoint.X, line.StartPoint.Y + m_moveOffset); line.EndPoint = new System.Drawing.Point(line.EndPoint.X, line.EndPoint.Y + m_moveOffset); // update the mapped grid line graphics path GraphicsPath path = new GraphicsPath(); path.AddLine(line.StartPoint, line.EndPoint); m_drawing.ULinePathList[m_drawing.SelectedUIndex] = path; // update the mapped segment line and its graphics path List <GraphicsPath> pathList = m_drawing.USegLinePathListList[m_drawing.SelectedUIndex]; List <SegmentLine2D> segLineList = line.Segments; for (int i = 0; i < segLineList.Count; i++) { // update the segment SegmentLine2D segLine2D = segLineList[i]; segLine2D.StartPoint = new System.Drawing.Point(segLine2D.StartPoint.X, segLine2D.StartPoint.Y + m_moveOffset); segLine2D.EndPoint = new System.Drawing.Point(segLine2D.EndPoint.X, segLine2D.EndPoint.Y + m_moveOffset); // update the segment's graphics path GraphicsPath gpath = new GraphicsPath(); path.AddLine(segLine2D.StartPoint, segLine2D.EndPoint); pathList[i] = gpath; } } // move a V line along the U direction else if (-1 != m_drawing.SelectedVIndex) { // convert the 2D data to 3D Autodesk.Revit.DB.XYZ xyz = new Autodesk.Revit.DB.XYZ(mousePosition.X, mousePosition.Y, 0); Vector4 vec = new Vector4(xyz); vec = m_drawing.Coordinates.RestoreMatrix.Transform(vec); double offset = vec.X - m_lineToBeMoved.FullCurve.GetEndPoint(0).X; xyz = new Autodesk.Revit.DB.XYZ(offset, 0, 0); Transaction act = new Transaction(m_activeDocument, Guid.NewGuid().GetHashCode().ToString()); act.Start(); try { ElementTransformUtils.MoveElement(m_activeDocument, m_lineToBeMoved.Id, xyz); } catch (System.Exception e) { TaskDialog.Show("Exception", e.Message); return(false); } act.Commit(); // update the grid line 2d GridLine2D line = m_drawing.VGridLines2D[m_drawing.SelectedVIndex]; line.StartPoint = new System.Drawing.Point(line.StartPoint.X + m_moveOffset, line.StartPoint.Y); line.EndPoint = new System.Drawing.Point(line.EndPoint.X + m_moveOffset, line.EndPoint.Y); // update the mapped grid line graphics path GraphicsPath path = new GraphicsPath(); path.AddLine(line.StartPoint, line.EndPoint); m_drawing.VLinePathList[m_drawing.SelectedVIndex] = path; // update the mapped segment line and its graphics path List <GraphicsPath> pathList = m_drawing.VSegLinePathListList[m_drawing.SelectedVIndex]; List <SegmentLine2D> segLineList = line.Segments; for (int i = 0; i < segLineList.Count; i++) { // update the segment SegmentLine2D segLine2D = segLineList[i]; segLine2D.StartPoint = new System.Drawing.Point(segLine2D.StartPoint.X + m_moveOffset, segLine2D.StartPoint.Y); segLine2D.EndPoint = new System.Drawing.Point(segLine2D.EndPoint.X + m_moveOffset, segLine2D.EndPoint.Y); // update the segment's graphics path GraphicsPath gpath = new GraphicsPath(); path.AddLine(segLine2D.StartPoint, segLine2D.EndPoint); pathList[i] = gpath; } } // line moved, the segment information changed, so reload all the geometry data this.ReloadGeometryData(); m_drawing.DrawObject.Clear(); return(true); }
/// <summary> /// add all the deleted segments back for a grid line /// </summary> public void AddAllSegments() { // verify that the mouse is inside the curtain grid area List <KeyValuePair <Line2D, Pen> > lines2D = m_drawing.DrawObject.Lines2D; if (lines2D.Count < 1) { return; } if (-1 != m_drawing.SelectedUIndex) { CurtainGridLine line = m_uGridLines[m_drawing.SelectedUIndex]; if (null != line) { try { Transaction act = new Transaction(m_activeDocument, Guid.NewGuid().GetHashCode().ToString()); act.Start(); line.AddAllSegments(); act.Commit(); } catch (System.Exception e) { TaskDialog.Show("Exception", e.Message); return; } } GridLine2D gridLine2D = m_drawing.UGridLines2D[m_drawing.SelectedUIndex]; gridLine2D.RemovedNumber = 0; foreach (SegmentLine2D segLine2D in gridLine2D.Segments) { segLine2D.Removed = false; } } else if (-1 != m_drawing.SelectedVIndex) { CurtainGridLine line = m_vGridLines[m_drawing.SelectedVIndex]; if (null != line) { try { Transaction act = new Transaction(m_activeDocument, Guid.NewGuid().GetHashCode().ToString()); act.Start(); line.AddAllSegments(); act.Commit(); } catch (System.Exception e) { TaskDialog.Show("Exception", e.Message); return; } } GridLine2D gridLine2D = m_drawing.VGridLines2D[m_drawing.SelectedVIndex]; gridLine2D.RemovedNumber = 0; foreach (SegmentLine2D segLine2D in gridLine2D.Segments) { segLine2D.Removed = false; } } this.ReloadGeometryData(); m_drawing.DrawObject.Clear(); }
/// <summary> /// add a new segment to the specified location /// </summary> public void AddSegment() { // verify that the mouse is inside the curtain grid area List <KeyValuePair <Line2D, Pen> > lines2D = m_drawing.DrawObject.Lines2D; if (lines2D.Count < 1) { return; } // the selected segment location is on a U grid line if (-1 != m_drawing.SelectedUIndex) { CurtainGridLine line = m_uGridLines[m_drawing.SelectedUIndex]; Curve curve = line.AllSegmentCurves.get_Item(m_drawing.SelectedUSegmentIndex); if (null != line && null != curve) { try { Transaction act = new Transaction(m_activeDocument, Guid.NewGuid().GetHashCode().ToString()); act.Start(); line.AddSegment(curve); act.Commit(); } catch (System.Exception e) { TaskDialog.Show("Exception", e.Message); return; } } GridLine2D gridLine2D = m_drawing.UGridLines2D[m_drawing.SelectedUIndex]; gridLine2D.RemovedNumber--; SegmentLine2D segLine2D = gridLine2D.Segments[m_drawing.SelectedUSegmentIndex]; segLine2D.Removed = false; gridLine2D.Segments[m_drawing.SelectedUSegmentIndex] = segLine2D; } // the selected segment location is on a V grid line else if (-1 != m_drawing.SelectedVIndex) { CurtainGridLine line = m_vGridLines[m_drawing.SelectedVIndex]; Curve curve = line.AllSegmentCurves.get_Item(m_drawing.SelectedVSegmentIndex); if (null != line && null != curve) { try { Transaction act = new Transaction(m_activeDocument, Guid.NewGuid().GetHashCode().ToString()); act.Start(); line.AddSegment(curve); act.Commit(); } catch (System.Exception e) { TaskDialog.Show("Exception", e.Message); return; } } GridLine2D gridLine2D = m_drawing.VGridLines2D[m_drawing.SelectedVIndex]; gridLine2D.RemovedNumber--; SegmentLine2D segLine2D = gridLine2D.Segments[m_drawing.SelectedVSegmentIndex]; segLine2D.Removed = false; gridLine2D.Segments[m_drawing.SelectedVSegmentIndex] = segLine2D; } this.ReloadGeometryData(); m_drawing.DrawObject.Clear(); }
/// <summary> /// toggle the selected grid line's Lock status: if it's locked, unlock it, vice versa /// </summary> public void LockOrUnlockSelectedGridLine() { CurtainGridLine line = null; GridLine2D line2D = new GridLine2D(); // get the selected grid line if (-1 != m_drawing.SelectedUIndex) { line = m_uGridLines[m_drawing.SelectedUIndex]; line2D = m_drawing.UGridLines2D[m_drawing.SelectedUIndex]; } else if (-1 != m_drawing.SelectedVIndex) { line = m_vGridLines[m_drawing.SelectedVIndex]; line2D = m_drawing.VGridLines2D[m_drawing.SelectedVIndex]; } else { return; } // lock/unlock the grid line if (null != line) { Transaction act = new Transaction(m_activeDocument, Guid.NewGuid().GetHashCode().ToString()); act.Start(); line.Lock = !line.Lock; act.Commit(); } // update the mapped line2D's data line2D.Locked = line.Lock; // clear the intermediate variables and instances m_drawing.DrawObject.Clear(); }
/// <summary> /// show the candicate new V grid line to be added. In "add vertical grid line" operation, /// there'll be a dash line following the movement of the mouse, it's drawn by this method /// </summary> /// <param name="mousePosition"> /// the location of the mouse cursor /// </param> /// <returns> /// if added successfully, return true; otherwise false (if the mouse location is invalid, it will return false) /// </returns> public bool AddDashVLine(System.Drawing.Point mousePosition) { bool mouseInGrid = VerifyMouseLocation(mousePosition); // mouse is outside the curtain grid boundary if (false == mouseInGrid) { m_mouseLocationValid = false; return false; } // if the mouse laps over another grid line, it's invalid bool isOverlapped = IsOverlapped(mousePosition, m_vLinePathList); if (true == isOverlapped) { m_mouseLocationValid = false; string msg = "It's not allowed to add grid line lapping over another grid line"; m_myDocument.Message = new KeyValuePair<string, bool>(msg, true); return false; } // there's no "overlap", it's valid else { string msg = "Specify a point within the curtain grid to locate the grid line"; m_myDocument.Message = new KeyValuePair<string, bool>(msg, false); } m_mouseLocationValid = true; // get a parallel V line first GridLine2D vLine2D; // for "Curtain Wall: Curtain Wall 1", there's no initial U/V grid lines, so we use the boundary // line instead (the same result) if (null == m_vGridLines2D || 0 == m_vGridLines2D.Count) { vLine2D = m_boundLines2D[1]; } else { vLine2D = m_vGridLines2D[0]; } System.Drawing.Point startPoint = vLine2D.StartPoint; System.Drawing.Point endPoint = vLine2D.EndPoint; // move the start point and the end point parallelly startPoint.X = mousePosition.X; endPoint.X = mousePosition.X; // get the dash u line GridLine2D dashVLine = new GridLine2D(startPoint, endPoint); // initialize the pan Pen redPen = new Pen(System.Drawing.Color.Red, m_sketchPenWidth); Brush brush = Brushes.Red; redPen.DashCap = DashCap.Flat; redPen.DashStyle = DashStyle.Dash; // add the dash line to the assistant line list for drawing m_drawObject = new DrawObject(dashVLine, redPen); return true; }
/// <summary> /// get all the segments of the specified grid line /// </summary> /// <param name="gridLine2D"> /// the grid line which wants to get all its segments /// </param> /// <param name="allCurves"> /// all the segments (include existent ones and skipped one) /// </param> /// <param name="skippedSegments"> /// the skipped segments /// </param> /// <param name="segPaths"> /// the GraphicsPath list contains all the segments /// </param> /// <param name="gridLineIndex"> /// the index of the grid line /// </param> private void GetSegments(GridLine2D gridLine2D, CurveArray allCurves, List<SegmentLine2D> skippedSegments, List<GraphicsPath> segPaths, int gridLineIndex) { int segIndex = -1; // convert the segments from Curve format to SegmentLine2D format (from 3D to 2D) foreach (Curve curve in allCurves) { // store the index of the segment in the grid line segIndex++; Autodesk.Revit.DB.XYZ point1 = curve.get_EndPoint(0); Autodesk.Revit.DB.XYZ point2 = curve.get_EndPoint(1); Vector4 v1 = new Vector4(point1); Vector4 v2 = new Vector4(point2); // transform from 3D point to 2D point v1 = m_coordinates.TransformMatrix.Transform(v1); v2 = m_coordinates.TransformMatrix.Transform(v2); // add the segment data SegmentLine2D segLine2D = new SegmentLine2D(); segLine2D.StartPoint = new System.Drawing.Point((int)v1.X, (int)v1.Y); segLine2D.EndPoint = new System.Drawing.Point((int)v2.X, (int)v2.Y); // if the segment is contained in the skipped list, set the Removed flag to true; otherwise false segLine2D.Removed = IsSegLineContained(skippedSegments, segLine2D); // if the segment is in a U grid line, set it true; otherwise false segLine2D.IsUSegment = gridLine2D.IsUGridLine; // the index of the parent grid line in the grid line list segLine2D.GridLineIndex = gridLineIndex; // the index of the segment in its parent grid line segLine2D.SegmentIndex = segIndex; if (true == segLine2D.Removed) { gridLine2D.RemovedNumber++; } gridLine2D.Segments.Add(segLine2D); // store the mapped graphics path GraphicsPath path = new GraphicsPath(); path.AddLine(segLine2D.StartPoint, segLine2D.EndPoint); segPaths.Add(path); } }
/// <summary> /// get the boundary lines of the curtain grid /// </summary> private void GetBoundLines2D() { for (int i = 0; i < m_geometry.GridVertexesXYZ.Count; i += 1) { Autodesk.Revit.DB.XYZ point1, point2; // connect the last point with the first point as a boundary line if (i == m_geometry.GridVertexesXYZ.Count - 1) { point1 = m_geometry.GridVertexesXYZ[i]; point2 = m_geometry.GridVertexesXYZ[0]; } else { point1 = m_geometry.GridVertexesXYZ[i]; point2 = m_geometry.GridVertexesXYZ[i + 1]; } Vector4 v1 = new Vector4(point1); Vector4 v2 = new Vector4(point2); // transform from 3D point to 2D point v1 = m_coordinates.TransformMatrix.Transform(v1); v2 = m_coordinates.TransformMatrix.Transform(v2); // stores the bounding coordinate int v1X = (int)v1.X; int v1Y = (int)v1.Y; int v2X = (int)v2.X; int v2Y = (int)v2.Y; // obtain the min and max point m_minX = v1X; m_minY = v1Y; if (v1X > m_maxX) { m_maxX = v1X; } else if (v1X < m_minX) { m_minX = v1X; } if (v2X > m_maxX) { m_maxX = v2X; } else if (v2X < m_minX) { m_minX = v2X; } if (v1Y > m_maxY) { m_maxY = v1Y; } if (v1Y < m_minY) { m_minY = v1Y; } if (v2Y > m_maxY) { m_maxY = v2Y; } if (v2Y < m_minY) { m_minY = v2Y; } // create the boundary line GridLine2D line2D = new GridLine2D(); line2D.StartPoint = new System.Drawing.Point((int)v1.X, (int)v1.Y); line2D.EndPoint = new System.Drawing.Point((int)v2.X, (int)v2.Y); m_boundLines2D.Add(line2D); // add the line to the mapped GraphicsPath list GraphicsPath path = new GraphicsPath(); path.AddLine(line2D.StartPoint, line2D.EndPoint); m_boundPath.Add(path); } }
/// <summary> /// convert the grid line in CurtainGridLine format to GridLine2D format /// in the Canvas area, the "System.Drawing.Point" instances are directly used, it's hard /// for us to use CurtainGridLine and Autodesk.Revit.DB.XYZ directly, so convert them to 2D data first /// </summary> /// <param name="line"> /// the grid line in CurtainGridLine format /// </param> /// <param name="segPaths"> /// the grid line in GraphicsPath format (the GraphicsPath contains the grid line in GridLine2D format) /// </param> /// <param name="gridLineIndex"> /// the index of the grid line /// </param> /// <returns> /// the converted grid line in GridLine2D format /// </returns> private GridLine2D ConvertToLine2D(CurtainGridLine line, List<GraphicsPath> segPaths, int gridLineIndex) { Curve curve = line.FullCurve; Autodesk.Revit.DB.XYZ point1 = curve.get_EndPoint(0); Autodesk.Revit.DB.XYZ point2 = curve.get_EndPoint(1); Vector4 v1 = new Vector4(point1); Vector4 v2 = new Vector4(point2); // transform from 3D point to 2D point v1 = m_coordinates.TransformMatrix.Transform(v1); v2 = m_coordinates.TransformMatrix.Transform(v2); // create a new line in GridLine2D format GridLine2D line2D = new GridLine2D(); line2D.StartPoint = new System.Drawing.Point((int)v1.X, (int)v1.Y); line2D.EndPoint = new System.Drawing.Point((int)v2.X, (int)v2.Y); line2D.Locked = line.Lock; line2D.IsUGridLine = line.IsUGridLine; // get which segments are skipped List<SegmentLine2D> skippedSegments = ConvertCurveToSegment(line.SkippedSegmentCurves); // get all the segments for the curtain grid (and tag the skipped ones out) GetSegments(line2D, line.AllSegmentCurves, skippedSegments, segPaths, gridLineIndex); return line2D; }