/* * This routine is used to invert the hole points, specifically the 'Y' points. * The html canvas has 0,0 at the upper left and 'Y' goes down. For the holegroup canvas * we want a 'Y' that goes up, because that's how the holes are overlaid and appear in * three dimensions, and how we think of them intuitively. To manage this we'll simply flip the * Y points for the duration of the time that they are being edited and reflip them when its time to save */ public void InvertHolePoints() { for (int i = 0; i < HoleGroupList.Count; i++) { HoleGroup hg = HoleGroupList.GetFrom(i); for (int j = 0; j < hg.HoleList.Length; j++) { /* * For all hole types the offset Y is inverted */ LayoutHole oHole = hg.HoleList[j]; oHole.OffsetY = -oHole.OffsetY; /* * For polygon hole types the individual Y's are inverted */ if (oHole.HoleType == "poly") { BoundaryPolygon oPolygon = BoundaryPolygonList.GetFrom(oHole.HoleTypeIndex); for (int k = 0; k < oPolygon.PointList.Length; k++) { Point3D p = oPolygon.PointList[k]; p.Y = -p.Y; } } } } }
//---------------------------------------------------------------------------- private bool TrySelectEllipse(LayoutHole oHole, int ScreenMouseX, int ScreenMouseY) { PointF MoveHandle = new PointF(0, 0); PointF ResizeHandle = new PointF(0, 0); BoundaryEllipse oEllipse = BoundaryEllipseList.GetFrom(oHole.HoleTypeIndex); // The move handle is the center MoveHandle = this.W2S(oHole.OffsetX, oHole.OffsetY); if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, MoveHandle)) { CurrentlySelectedHole = oHole; MostRecentlySelectedHole = oHole; CurrentlySelectedHandleType = eHandleType.MoveHandle; return(true); } // The resize handle is the lower right corner ResizeHandle = this.W2S(oHole.OffsetX + oEllipse.Width / 2, oHole.OffsetY + oEllipse.Height / 2); if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, ResizeHandle)) { CurrentlySelectedHole = oHole; MostRecentlySelectedHole = oHole; CurrentlySelectedHandleType = eHandleType.ResizeHandle; return(true); } return(false); }
//---------------------------------------------------------------------------- private bool TrySelectRectangle(LayoutHole oHole, int ScreenMouseX, int ScreenMouseY) { PointF MoveHandle = new PointF(0, 0); PointF ResizeHandle = new PointF(0, 0); BoundaryRectangle oRect = BoundaryRectangleList.GetFrom(oHole.HoleTypeIndex); // The move handle is the lower left MoveHandle = this.W2S(oHole.OffsetX, oHole.OffsetY); if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, MoveHandle)) { CurrentlySelectedHole = oHole; MostRecentlySelectedHole = oHole; CurrentlySelectedHandleType = eHandleType.MoveHandle; return(true); } // The resize handle is the lower right corner // the position of the handle is based on the zoom float HandleOffsetX = oRect.Width / this.CurrentZoom; float HandleOffsetY = oRect.Height / this.CurrentZoom; ResizeHandle = new PointF(MoveHandle.X + HandleOffsetX, MoveHandle.Y + HandleOffsetY); if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, ResizeHandle)) { CurrentlySelectedHole = oHole; MostRecentlySelectedHole = oHole; CurrentlySelectedHandleType = eHandleType.ResizeHandle; return(true); } return(false); }
//------------------------------------------------------ private void DrawShapes_Polygon(LayoutHole oHole, bool IsCurrentHole) { BoundaryPolygon bp = BoundaryPolygonList.GetFrom(oHole.HoleTypeIndex); PointF ScreenOffset = this.W2S(oHole.OffsetX, oHole.OffsetY); for (int i = 0; i < bp.PointList.Length; i++) { int FromIndex = i; int ToIndex = i + 1; if (ToIndex == bp.PointList.Length) { ToIndex = 0; // Wrap at end } Point3D FromPoint = bp.PointList[FromIndex]; float fdx = FromPoint.X / CurrentZoom; float fdy = FromPoint.Y / CurrentZoom; Point3D ToPoint = bp.PointList[ToIndex]; float tdx = ToPoint.X / CurrentZoom; float tdy = ToPoint.Y / CurrentZoom; PointF ScreenFrom = new PointF(ScreenOffset.X + fdx, ScreenOffset.Y + fdy); PointF ScreenTo = new PointF(ScreenOffset.X + tdx, ScreenOffset.Y + tdy); // Draw handles string color = "rgba(255,0,0,.5)"; if (IsCurrentHole && i == MostRecentlySelectedPolygonVertexIndex) { color = "#0000FF"; } this.DrawCircle(color, 10, ScreenFrom.X, ScreenFrom.Y); PointF oCenter = EdgeCenter(ScreenFrom, ScreenTo); // Draw the handle for the edge color = "rgba(0,255,0,.5)"; if (IsCurrentHole && i == MostRecentlySelectedPolygonEdgeIndex) { color = "#0000FF"; } this.DrawRectangle(color, 10, 10, oCenter.X, oCenter.Y); // Draw Line this.DrawLine(ShapeStrokeColor, (float)0.5, ScreenFrom, ScreenTo); // Draw the move handle PointF oMove = PolygonCenter(bp); float mdx = oMove.X / CurrentZoom; float mdy = oMove.Y / CurrentZoom; oMove = new PointF(ScreenOffset.X + mdx, ScreenOffset.Y + mdy); color = IsCurrentHole ? "#0000FF" : "rgba(255,0,0,.5)"; // Draw the move handle this.DrawCircle(color, 10, oMove.X, oMove.Y); } }
public void AddHoleToHoleGroup(HoleGroup hg, LayoutHole oNewHole) { #if DOTNET List <LayoutHole> tmp = new List <LayoutHole>(hg.HoleList); tmp.Add(oNewHole); hg.HoleList = tmp.ToArray(); #else hg.HoleList.push(oNewHole); #endif }
// Add a polygon. This is managed with a simplelayout object public void AddPolygon(int ScreenOffsetX, int ScreenOffsetY, int InitialSides, int Radius) { if (MostRecentlySelectedHoleGroup == null) { return; } BoundaryPolygon oPolygon = new BoundaryPolygon(); oPolygon.PointList = new Point3D[InitialSides]; float Angle = 0; float AngleDelta = (float)Math.PI * 2 / InitialSides; for (int i = 0; i < InitialSides; i++) { Point3D p = new Point3D(); #if DOTNET float x = (float)Math.Cos(Angle) * Radius; float y = (float)Math.Sin(Angle) * Radius; #else float x = (float)Math.cos(Angle) * Radius; float y = (float)Math.sin(Angle) * Radius; #endif p.X = x; p.Y = y; oPolygon.PointList[i] = p; Angle += AngleDelta; } /* * Create a hole and boundary polygon object */ PointF WorldOffset = this.S2W(ScreenOffsetX, ScreenOffsetY); LayoutHole oHole = new LayoutHole(); oHole.HoleType = "poly"; oHole.HoleTypeIndex = BoundaryPolygonList.Count; oHole.OffsetX = WorldOffset.X; oHole.OffsetY = WorldOffset.Y; AddHoleToHoleGroup(MostRecentlySelectedHoleGroup, oHole); CurrentlySelectedHole = oHole; MostRecentlySelectedHole = oHole; BoundaryPolygonList.Add(oPolygon); // trigger redraw DrawShapes(); }
public void LoadFromJSON( HoleGroup[] HoleGroupArray, BoundaryRectangle[] RectangleArray, BoundaryEllipse[] EllipseArray, BoundaryPolygon[] PolygonArray) { HoleGroupList = new List <HoleGroup>(); for (int i = 0; i < HoleGroupArray.Length; i++) { HoleGroup hg = new HoleGroup(); hg.HoleGroupID = HoleGroupArray[i].HoleGroupID; /* * When the objects get here in JS the holelist is no longer a list type, its an array type because * of serialization. */ int len = GetHoleListLength(HoleGroupArray[i].HoleList); for (int j = 0; j < len; j++) { LayoutHole oHoleToAdd = HoleGroupArray[i].HoleList[j]; AddHoleToHoleGroup(hg, oHoleToAdd); } HoleGroupList.Add(hg); } BoundaryRectangleList = new List <BoundaryRectangle>(); for (int i = 0; i < RectangleArray.Length; i++) { BoundaryRectangleList.Add(RectangleArray[i]); } BoundaryEllipseList = new List <BoundaryEllipse>(); for (int i = 0; i < EllipseArray.Length; i++) { BoundaryEllipseList.Add(EllipseArray[i]); } BoundaryPolygonList = new List <BoundaryPolygon>(); for (int i = 0; i < PolygonArray.Length; i++) { BoundaryPolygonList.Add(PolygonArray[i]); } /* * Now flip all of the Y points so that positive Y values go 'up' */ InvertHolePoints(); }
public void DuplicateCurrentHole() { if (MostRecentlySelectedHole == null) { return; } LayoutHole oHole = LayoutHole.CopyFrom(MostRecentlySelectedHole); // Add at an offset so it will be easy to see oHole.OffsetX += 10; oHole.OffsetY += 10; // Create a new version of the instance of the hole int ndx = MostRecentlySelectedHole.HoleTypeIndex; switch (MostRecentlySelectedHole.HoleType) { case "ell": oHole.HoleTypeIndex = BoundaryEllipseList.Count; BoundaryEllipse e = BoundaryEllipseList.GetFrom(ndx); BoundaryEllipseList.Add(BoundaryEllipse.CopyFrom(e)); break; case "rect": oHole.HoleTypeIndex = BoundaryRectangleList.Count; BoundaryRectangle r = BoundaryRectangleList.GetFrom(ndx); BoundaryRectangleList.Add(BoundaryRectangle.CopyFrom(r)); break; case "poly": oHole.HoleTypeIndex = BoundaryPolygonList.Count; BoundaryPolygon p = BoundaryPolygonList.GetFrom(ndx); BoundaryPolygonList.Add(BoundaryPolygon.CopyFrom(p)); break; } // Add the new hole to the hole group AddHoleToHoleGroup(MostRecentlySelectedHoleGroup, oHole); // trigger a repaint DrawShapes(); }
public void AddEllipse(int ScreenOffsetX, int ScreenOffsetY, int Width, int Height) { if (MostRecentlySelectedHoleGroup == null) { return; } PointF WorldOffset = this.S2W(ScreenOffsetX, ScreenOffsetY); LayoutHole oHole = new LayoutHole(); oHole.HoleType = "ell"; oHole.OffsetX = WorldOffset.X; oHole.OffsetY = WorldOffset.Y; /* * Save this as the current and most recently selected * The most recently selected is used for commands after the mouse is up */ CurrentlySelectedHole = oHole; MostRecentlySelectedHole = oHole; /* * The index is the at the end of the current list. This means we will have to manage the index values * when they are deleted */ oHole.HoleTypeIndex = BoundaryEllipseList.Count; AddHoleToHoleGroup(MostRecentlySelectedHoleGroup, oHole); /* * Now create and add the ellipse */ BoundaryEllipse ell = new BoundaryEllipse(); ell.Width = Width; ell.Height = Height; BoundaryEllipseList.Add(ell); // trigger redraw DrawShapes(); }
public void AddRectangle(int ScreenOffsetX, int ScreenOffsetY, int Width, int Height) { if (MostRecentlySelectedHoleGroup == null) { return; } PointF WorldOffset = this.S2W(ScreenOffsetX, ScreenOffsetY); LayoutHole oHole = new LayoutHole(); oHole.HoleType = "rect"; oHole.OffsetX = WorldOffset.X; oHole.OffsetY = WorldOffset.Y; /* * Save this as the current and most recently selected */ CurrentlySelectedHole = oHole; MostRecentlySelectedHole = oHole; /* * The index is the at the end of the current list. This means we will have to manage the index values * when they are deleted */ oHole.HoleTypeIndex = BoundaryRectangleList.Count; AddHoleToHoleGroup(MostRecentlySelectedHoleGroup, oHole); /* * Now create and add the rectangle */ BoundaryRectangle rect = new BoundaryRectangle(); rect.Width = Width; rect.Height = Height; BoundaryRectangleList.Add(rect); // trigger draw shapes DrawShapes(); }
//------------------------------------------------------- private void DrawShapes_Ellipse(LayoutHole oHole, bool IsCurrentHole) { BoundaryEllipse oEllipse = BoundaryEllipseList.GetFrom(oHole.HoleTypeIndex); PointF Screen = this.W2S(oHole.OffsetX, oHole.OffsetY); float SWidth = oEllipse.Width / CurrentZoom; float SHeight = oEllipse.Height / CurrentZoom; string color = IsCurrentHole ? "#0000FF" : "rgba(255,0,0,.5)"; // Draw the move handle this.DrawCircle(color, 10, Screen.X, Screen.Y); // draw the actual ellipse this.DrawEllipse(ShapeStrokeColor, SWidth, SHeight, Screen.X, Screen.Y); // draw the resize handle this.DrawRectangle("rgba(0,255,0,.5)", 10, 10, Screen.X + SWidth / 2, Screen.Y + SHeight / 2); }
/// <summary> /// Find the edge that's closest to the mouse X,Y /// </summary> /// <param name="ScreenMouseX"></param> /// <param name="ScreenMouseY"></param> /// <returns></returns> /// public bool TryHoleSelect(int ScreenMouseX, int ScreenMouseY) { if (MostRecentlySelectedHoleGroup == null) { return(false); } for (int i = 0; i < GetHoleListLength(MostRecentlySelectedHoleGroup.HoleList); i++) { LayoutHole oHole = MostRecentlySelectedHoleGroup.HoleList[i]; PointF MoveHandle = new PointF(0, 0); PointF ResizeHandle = new PointF(0, 0); switch (oHole.HoleType) { case "rect": if (TrySelectRectangle(oHole, ScreenMouseX, ScreenMouseY)) { return(true); } break; case "poly": if (TrySelectPolygon(oHole, ScreenMouseX, ScreenMouseY)) { return(true); } break; case "ell": if (TrySelectEllipse(oHole, ScreenMouseX, ScreenMouseY)) { return(true); } break; } } return(false); }
//------------------------------------------------------- private void DrawShapes_Rectangle(LayoutHole oHole, bool IsCurrentHole) { BoundaryRectangle oRect = BoundaryRectangleList.GetFrom(oHole.HoleTypeIndex); PointF Screen = this.W2S(oHole.OffsetX, oHole.OffsetY); string color = IsCurrentHole ? "#0000FF" : "#ff0000"; // Draw the move handle this.DrawCircle(color, HandleSize, Screen.X, Screen.Y); // Adjust the width and height for zoom float SWidth = oRect.Width / CurrentZoom; float SHeight = oRect.Height / CurrentZoom; // Draw the rectangle as a set of lines so we can control how its positioned. The offset is the lower left color = ShapeStrokeColor; // The offset is to the lower left PointF LowerLeft = Screen; PointF LowerRight = new PointF(LowerLeft.X + SWidth, LowerLeft.Y); this.DrawLine(color, 1, LowerLeft, LowerRight); PointF UpperRight = new PointF(LowerLeft.X + SWidth, LowerLeft.Y + SHeight); this.DrawLine(color, 1, LowerRight, UpperRight); PointF UpperLeft = new PointF(LowerLeft.X, LowerLeft.Y + SHeight); this.DrawLine(color, 1, UpperRight, UpperLeft); // Last line this.DrawLine(color, 1, UpperLeft, LowerLeft); // draw the resize handle this.DrawRectangle("#00FF00", HandleSize, HandleSize, Screen.X + SWidth, Screen.Y + SHeight - HandleSize); }
public void DeleteCurrentHole() { if (MostRecentlySelectedHole == null) { return; } int IndexToDelete = -1; switch (MostRecentlySelectedHole.HoleType) { case "ell": // Delete this index // Find all references to hole values greater than this one and reduce them by one so the indices are correct IndexToDelete = -1; for (int i = 0; i < GetHoleListLength(MostRecentlySelectedHoleGroup.HoleList); i++) { LayoutHole oHole = MostRecentlySelectedHoleGroup.HoleList[i]; if (MostRecentlySelectedHole == oHole) { IndexToDelete = i; } if (oHole.HoleType == "ell" && oHole.HoleTypeIndex > MostRecentlySelectedHole.HoleTypeIndex) { oHole.HoleTypeIndex--; } } // Delete this hole RemoveHoleFromHoleGroup(MostRecentlySelectedHoleGroup, IndexToDelete); // Delete this shape BoundaryEllipseList.RemoveAt(MostRecentlySelectedHole.HoleTypeIndex); break; case "rect": // Delete this index // Find all references to hole values greater than this one and reduce them by one so the indices are correct IndexToDelete = -1; for (int i = 0; i < GetHoleListLength(MostRecentlySelectedHoleGroup.HoleList); i++) { LayoutHole oHole = MostRecentlySelectedHoleGroup.HoleList[i]; if (MostRecentlySelectedHole == oHole) { IndexToDelete = i; } if (oHole.HoleType == "rect" && oHole.HoleTypeIndex > MostRecentlySelectedHole.HoleTypeIndex) { oHole.HoleTypeIndex--; } } // Delete this hole RemoveHoleFromHoleGroup(MostRecentlySelectedHoleGroup, IndexToDelete); // Delete this shape BoundaryRectangleList.RemoveAt(MostRecentlySelectedHole.HoleTypeIndex); break; case "poly": // Find all references to hole values greater than this one and reduce them by one so the indices are correct IndexToDelete = -1; for (int i = 0; i < GetHoleListLength(MostRecentlySelectedHoleGroup.HoleList); i++) { LayoutHole oHole = MostRecentlySelectedHoleGroup.HoleList[i]; if (MostRecentlySelectedHole == oHole) { IndexToDelete = i; } if (oHole.HoleType == "poly" && oHole.HoleTypeIndex > MostRecentlySelectedHole.HoleTypeIndex) { oHole.HoleTypeIndex--; } } // Delete this hole RemoveHoleFromHoleGroup(MostRecentlySelectedHoleGroup, IndexToDelete); // Delete this shape BoundaryPolygonList.RemoveAt(MostRecentlySelectedHole.HoleTypeIndex); break; } // trigger a repaint DrawShapes(); }
//-------------------------------------------------------------------------- /* * A Polygon can be selected in any of these ways: * 1. A vertex can be selected, which makes it the active vertex * 2. An edge can be selected, which makes it the active edge * 3. The move handle can be selected. The move handle is generated as the average of the points of the polygon */ private bool TrySelectPolygon(LayoutHole oHole, int ScreenMouseX, int ScreenMouseY) { PointF MoveHandle = new PointF(0, 0); float dx; float dy; BoundaryPolygon oPolygon = BoundaryPolygonList.GetFrom(oHole.HoleTypeIndex); PointF ScreenOffset = this.W2S(oHole.OffsetX, oHole.OffsetY); /* * See if this is one of the vertices */ for (int i = 0; i < oPolygon.PointList.Length; i++) { Point3D p = oPolygon.PointList[i]; dx = p.X / CurrentZoom; dy = p.Y / CurrentZoom; PointF Target = new PointF(ScreenOffset.X + dx, ScreenOffset.Y + dy); if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, Target)) { CurrentlySelectedHole = oHole; // Most recently selected is used for commands that happen after the mouse is up MostRecentlySelectedHole = oHole; CurrentlySelectedHandleType = eHandleType.VertexHandle; CurrentlySelectedPolygonVertexIndex = i; // The most recently used is for commands that happen after the mouse is up MostRecentlySelectedPolygonVertexIndex = i; return(true); } } /* * See if this is one of the edges */ for (int i = 0; i < oPolygon.PointList.Length; i++) { int FromIndex = i; int ToIndex = i + 1; if (ToIndex == oPolygon.PointList.Length) { ToIndex = 0; } Point3D FromPoint = oPolygon.PointList[FromIndex]; dx = FromPoint.X / CurrentZoom; dy = FromPoint.Y / CurrentZoom; PointF pFrom = new PointF(ScreenOffset.X + dx, ScreenOffset.Y + dy); Point3D ToPoint = oPolygon.PointList[ToIndex]; dx = ToPoint.X / CurrentZoom; dy = ToPoint.Y / CurrentZoom; PointF pTo = new PointF(ScreenOffset.X + dx, ScreenOffset.Y + dy); PointF Target = EdgeCenter(pFrom, pTo); if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, Target)) { CurrentlySelectedHole = oHole; // Most recently selected is used for commands that happen after the mouse is up MostRecentlySelectedHole = oHole; CurrentlySelectedHandleType = eHandleType.EdgeHandle; CurrentlySelectedPolygonEdgeIndex = i; // The most recently used is for commands that happen after the mouse is up MostRecentlySelectedPolygonEdgeIndex = i; return(true); } } /* * See if this is the move handle at the center of the polygon */ PointF pCenter = PolygonCenter(oPolygon); dx = pCenter.X / CurrentZoom; dy = pCenter.Y / CurrentZoom; pCenter = new PointF(ScreenOffset.X + dx, ScreenOffset.Y + dy); if (IsHitOnTarget(ScreenMouseX, ScreenMouseY, pCenter)) { CurrentlySelectedHole = oHole; // Most recently selected is used for commands that happen after the mouse is up MostRecentlySelectedHole = oHole; CurrentlySelectedHandleType = eHandleType.MoveHandle; return(true); } return(false); }
// --------------------------------------------------- public override void DrawShapes() { #if DOTNET // The model for .net is to invalidate and let the paint handler draw. if (oGraphics == null && DrawPrimitives == null) { return; } #else #endif bool bIsCurrentHole = false; if (SubControl == 0) { this.Clear("#FFFFFF"); DrawGrid(); DrawAxis(); } /* * If specified draw in a shaded area that represents the current edge having holes designed for it */ if (ShadeHeight > 0 && ShadeLength > 0) { PointF LowerLeft = this.W2S(0, 0); PointF LowerRight = this.W2S(ShadeLength, 0); PointF UpperRight = this.W2S(ShadeLength, -ShadeHeight); PointF UpperLeft = this.W2S(0, -ShadeHeight); this.DrawLine("rgba(100,100,150,.7", 1, LowerLeft, LowerRight); this.DrawLine("rgba(100,100,150,.7", 1, LowerRight, UpperRight); this.DrawLine("rgba(100,100,150,.7", 1, UpperRight, UpperLeft); this.DrawLine("rgba(100,100,150,.7", 1, UpperLeft, LowerLeft); } if (this.MostRecentlySelectedHoleGroup == null) { return; } #if DOTNET int len = MostRecentlySelectedHoleGroup.HoleList.Length; #else int len = MostRecentlySelectedHoleGroup.HoleList.length; #endif for (int i = 0; i < len; i++) { LayoutHole oHole = MostRecentlySelectedHoleGroup.HoleList[i]; PointF Screen = this.W2S(oHole.OffsetX, oHole.OffsetY); bIsCurrentHole = oHole == MostRecentlySelectedHole; switch (oHole.HoleType) { case "rect": DrawShapes_Rectangle(oHole, bIsCurrentHole); break; case "poly": DrawShapes_Polygon(oHole, bIsCurrentHole); break; case "ell": DrawShapes_Ellipse(oHole, bIsCurrentHole); break; } } }