// 圆角代码 public void Round(System.Drawing.Region region) { // ----------------------------------------------------------------------------------------------- // 已经是.net提供给我们的最容易的改窗体的属性了(以前要自己调API) System.Drawing.Drawing2D.GraphicsPath oPath = new System.Drawing.Drawing2D.GraphicsPath(); int x = 0; int y = 0; int thisWidth = this.Width; int thisHeight = this.Height; int angle = _Radius; if (angle > 0) { oPath.AddEllipse(x, y, this.Width, this.Height); // 左下角 oPath.CloseAllFigures(); Region = new System.Drawing.Region(oPath); } // ----------------------------------------------------------------------------------------------- else { oPath.AddLine(x + angle, y, thisWidth - angle, y); // 顶端 oPath.AddLine(thisWidth, y + angle, thisWidth, thisHeight - angle); // 右边 oPath.AddLine(thisWidth - angle, thisHeight, x + angle, thisHeight); // 底边 oPath.AddLine(x, y + angle, x, thisHeight - angle); oPath.Flatten(); // 左边 oPath.CloseAllFigures(); Region = new System.Drawing.Region(oPath); } }
//------------------------------------------------------------------------------------------------------------------------------------------------- //------------------------------------------- DRAWING CURVE ------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------------------------------------------------------- public void DrawCurve(List <System.Drawing.Point> points, Color color, float thickness, float worldScale) { System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath(System.Drawing.Drawing2D.FillMode.Winding); path.AddCurve(points.ToArray()); path.Flatten(); PointF[] finalPoints = path.PathPoints; path.Dispose(); //Convert point to vector2 if (finalPoints.Length < 2) { return; } float finalThickness = thickness * worldScale; if (finalThickness < 1) { finalThickness = 1; } Vector2D vectorThickNess = new Vector2D(finalThickness, finalThickness); for (int i = 1; i < finalPoints.Length; i++) { Gorgon.CurrentRenderTarget.Line((int)((float)finalPoints[i - 1].X * worldScale), (int)((float)finalPoints[i - 1].Y * worldScale), (int)(((float)finalPoints[i].X - (float)finalPoints[i - 1].X) * worldScale), (int)(((float)finalPoints[i].Y - (float)finalPoints[i - 1].Y) * worldScale), color, vectorThickNess); } }
/// <summary> /// takes in a parsed path and returns a list of points that can be used to draw the path /// </summary> /// <returns>The drawing points.</returns> /// <param name="segments">Segments.</param> public Vector2[] GetDrawingPoints(List <SvgPathSegment> segments, float flatness = 3) { var path = new System.Drawing.Drawing2D.GraphicsPath(); for (var j = 0; j < segments.Count; j++) { var segment = segments[j]; if (segment is SvgMoveToSegment) { path.StartFigure(); } else if (segment is SvgCubicCurveSegment) { var cubicSegment = segment as SvgCubicCurveSegment; path.AddBezier(ToDrawPoint(segment.Start), ToDrawPoint(cubicSegment.FirstCtrlPoint), ToDrawPoint(cubicSegment.SecondCtrlPoint), ToDrawPoint(segment.End)); } else if (segment is SvgClosePathSegment) { // important for custom line caps. Force the path the close with an explicit line, not just an implicit close of the figure. if (path.PointCount > 0 && !path.PathPoints[0].Equals(path.PathPoints[path.PathPoints.Length - 1])) { var i = path.PathTypes.Length - 1; while (i >= 0 && path.PathTypes[i] > 0) { i--; } if (i < 0) { i = 0; } path.AddLine(path.PathPoints[path.PathPoints.Length - 1], path.PathPoints[i]); } path.CloseFigure(); } else if (segment is SvgLineSegment) { path.AddLine(ToDrawPoint(segment.Start), ToDrawPoint(segment.End)); } else if (segment is SvgQuadraticCurveSegment) { var quadSegment = segment as SvgQuadraticCurveSegment; path.AddBezier(ToDrawPoint(segment.Start), ToDrawPoint(quadSegment.FirstCtrlPoint), ToDrawPoint(quadSegment.SecondCtrlPoint), ToDrawPoint(segment.End)); } else { Debug.Warn("unknown type in getDrawingPoints"); } } path.Flatten(new System.Drawing.Drawing2D.Matrix(), flatness); return(System.Array.ConvertAll(path.PathPoints, i => new Vector2(i.X, i.Y))); }
public void TabControl7_GetTabRegion(object sender, Thinksea.Windows.Forms.MdiTabControl.TabControl.GetTabRegionEventArgs e) { System.Drawing.Drawing2D.GraphicsPath x = new System.Drawing.Drawing2D.GraphicsPath(); x.AddArc(new Rectangle(0, 0, e.TabWidth, e.TabHeight * 2 / 3), 0, -180); x.Flatten(); System.Drawing.Point[] temp_array = e.Points; Array.Resize(ref temp_array, x.PointCount); e.Points = temp_array; for (int i = 0; i <= x.PointCount - 1; i++) { e.Points[i] = new Point(System.Convert.ToInt32(x.PathPoints[i].X), System.Convert.ToInt32(x.PathPoints[i].Y)); } }
/// <summary> /// takes in a parsed path and returns a list of points that can be used to draw the path /// </summary> /// <returns>The drawing points.</returns> /// <param name="segments">Segments.</param> public Vector2[] getDrawingPoints( List<SvgPathSegment> segments, float flatness = 3 ) { var path = new System.Drawing.Drawing2D.GraphicsPath(); for( var j = 0; j < segments.Count; j++ ) { var segment = segments[j]; if( segment is SvgMoveToSegment ) { path.StartFigure(); } else if( segment is SvgCubicCurveSegment ) { var cubicSegment = segment as SvgCubicCurveSegment; path.AddBezier( toDrawPoint( segment.start ), toDrawPoint( cubicSegment.firstCtrlPoint ), toDrawPoint( cubicSegment.secondCtrlPoint ), toDrawPoint( segment.end ) ); } else if( segment is SvgClosePathSegment ) { // important for custom line caps. Force the path the close with an explicit line, not just an implicit close of the figure. if( path.PointCount > 0 && !path.PathPoints[0].Equals( path.PathPoints[path.PathPoints.Length - 1] ) ) { var i = path.PathTypes.Length - 1; while( i >= 0 && path.PathTypes[i] > 0 ) i--; if( i < 0 ) i = 0; path.AddLine( path.PathPoints[path.PathPoints.Length - 1], path.PathPoints[i] ); } path.CloseFigure(); } else if( segment is SvgLineSegment ) { path.AddLine( toDrawPoint( segment.start ), toDrawPoint( segment.end ) ); } else if( segment is SvgQuadraticCurveSegment ) { var quadSegment = segment as SvgQuadraticCurveSegment; path.AddBezier( toDrawPoint( segment.start ), toDrawPoint( quadSegment.firstCtrlPoint ), toDrawPoint( quadSegment.secondCtrlPoint ), toDrawPoint( segment.end ) ); } else { Debug.warn( "unknown type in getDrawingPoints" ); } } path.Flatten( new System.Drawing.Drawing2D.Matrix(), flatness ); return System.Array.ConvertAll( path.PathPoints, i => new Vector2( i.X, i.Y ) ); }
public override System.Drawing.RectangleF GetTransformedVObjectBounds() { // // We cannot use evident way to get bounds of the Path, something like this: // // return this.Path.GetBounds(_matrix, _pen); // // because this implementation returns wrong values. It seems that the GraphicsPath algorithm // first finds bounds and after that applies matrix! Also it returns wrong (too large) // rectangle for curves (e.g. for ellipse). To avoid first issue we have to clone path // and manually transform it. To avoid second problem we have to use Flatten() method. // using (System.Drawing.Drawing2D.GraphicsPath c = (System.Drawing.Drawing2D.GraphicsPath) this.Path.Clone()) { c.Flatten(_matrix, 1.0f); return(c.GetBounds(_identityMatrix, _pen)); } }
/// <summary> /// Repaints the form with cool background and stuff /// </summary> /// <param name="graph">The graphics object to paint to, the element will be drawn to 0,0</param> override public void Paint(Graphics graph) { //Draws Rectangular Shapes if (Shape == ModelShapes.Arrow) { _arrowPath = new System.Drawing.Drawing2D.GraphicsPath(); //Draws the basic shape Pen arrowPen; if (Highlight < 1) arrowPen = new Pen(Color.Cyan, 3F); else arrowPen = new Pen(Color.Black, 3F); //Draws the curved arrow Point[] lineArray = new Point[4]; lineArray[0] = new Point(_startPoint.X, _startPoint.Y); lineArray[1] = new Point(_startPoint.X - ((_startPoint.X - _stopPoint.X) / 3), _startPoint.Y); lineArray[2] = new Point(_stopPoint.X - ((_stopPoint.X - _startPoint.X) / 3), _stopPoint.Y); lineArray[3] = new Point(_stopPoint.X, _stopPoint.Y); graph.DrawBeziers(arrowPen, lineArray); _arrowPath.AddBeziers(lineArray); _arrowPath.Flatten(); //Draws the arrow head Point[] arrowArray = new Point[3]; arrowArray[0] = _stopPoint; arrowArray[1] = new Point(_stopPoint.X - (5 * Math.Sign(_stopPoint.X - _startPoint.X)),_stopPoint.Y - 2); arrowArray[2] = new Point(_stopPoint.X - (5 * Math.Sign(_stopPoint.X - _startPoint.X)), _stopPoint.Y + 2); graph.DrawPolygon(arrowPen,arrowArray); //Garbage collection arrowPen.Dispose(); } }
protected void PaintOneRange(int axisNumber, Graphics g, IPlotArea layer, IPlotRange range, Processed2DPlotData pdata) { const double logicalClampMinimum = -10; const double logicalClampMaximum = 11; _skipFrequency = Math.Max(1, _skipFrequency); // Plot error bars for the dependent variable (y) var ptArray = pdata.PlotPointsInAbsoluteLayerCoordinates; var posErrCol = PositiveErrorColumn; var negErrCol = NegativeErrorColumn; if (null != posErrCol && !typeof(double).IsAssignableFrom(posErrCol.ItemType)) posErrCol = null; // TODO make this an runtime paint error to be reported if (null != negErrCol && !typeof(double).IsAssignableFrom(negErrCol.ItemType)) negErrCol = null; // TODO make this an runtime paint error to be reported if (posErrCol == null && negErrCol == null) return; // nothing to do if both error columns are null var strokePen = _pen.Clone(); System.Drawing.Drawing2D.GraphicsPath errorBarPath = new System.Drawing.Drawing2D.GraphicsPath(); Region oldClippingRegion = g.Clip; Region newClip = (Region)oldClippingRegion.Clone(); int lower = range.LowerBound; int upper = range.UpperBound; for (int j = lower; j < upper; j += _skipFrequency) { int originalRowIndex = range.GetOriginalRowIndexFromPlotPointIndex(j); double symbolSize = null == _cachedSymbolSizeForIndexFunction ? _symbolSize : _cachedSymbolSizeForIndexFunction(originalRowIndex); strokePen.Width = (_lineWidth1Offset + _lineWidth1Factor * symbolSize); if (null != _cachedColorForIndexFunction) strokePen.Color = GdiColorHelper.ToNamedColor(_cachedColorForIndexFunction(originalRowIndex), "VariableColor"); if (null != strokePen.EndCap) strokePen.EndCap = strokePen.EndCap.WithMinimumAbsoluteAndRelativeSize(symbolSize * _endCapSizeFactor + _endCapSizeOffset, 1 + 1E-6); AltaxoVariant vMeanPhysical = pdata.GetPhysical(axisNumber, originalRowIndex); Logical3D logicalMean = layer.GetLogical3D(pdata, originalRowIndex); logicalMean.RX += _cachedLogicalShiftX; logicalMean.RY += _cachedLogicalShiftY; if (!Calc.RMath.IsInIntervalCC(logicalMean.RX, logicalClampMinimum, logicalClampMaximum)) continue; if (!Calc.RMath.IsInIntervalCC(logicalMean.RY, logicalClampMinimum, logicalClampMaximum)) continue; var vMeanLogical = logicalMean.GetR(axisNumber); Logical3D logicalPos = logicalMean; Logical3D logicalNeg = logicalMean; bool logicalPosValid = false; bool logicalNegValid = false; switch (_meaningOfValues) { case ValueInterpretation.AbsoluteError: { if (posErrCol != null) { var vPosLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(vMeanPhysical + Math.Abs(posErrCol[originalRowIndex])); vPosLogical = Calc.RMath.ClampToInterval(vPosLogical, logicalClampMinimum, logicalClampMaximum); logicalPos.SetR(axisNumber, vPosLogical); logicalPosValid = !logicalPos.IsNaN && vPosLogical != vMeanLogical; } if (negErrCol != null) { var vNegLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(vMeanPhysical - Math.Abs(negErrCol[originalRowIndex])); vNegLogical = Calc.RMath.ClampToInterval(vNegLogical, logicalClampMinimum, logicalClampMaximum); logicalNeg.SetR(axisNumber, vNegLogical); logicalNegValid = !logicalNeg.IsNaN && vNegLogical != vMeanLogical; } } break; case ValueInterpretation.RelativeError: { if (posErrCol != null) { var vPosLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(vMeanPhysical * (1 + Math.Abs(posErrCol[originalRowIndex]))); vPosLogical = Calc.RMath.ClampToInterval(vPosLogical, logicalClampMinimum, logicalClampMaximum); logicalPos.SetR(axisNumber, vPosLogical); logicalPosValid = !logicalPos.IsNaN && vPosLogical != vMeanLogical; } if (negErrCol != null) { var vNegLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(vMeanPhysical * (1 - Math.Abs(negErrCol[originalRowIndex]))); vNegLogical = Calc.RMath.ClampToInterval(vNegLogical, logicalClampMinimum, logicalClampMaximum); logicalNeg.SetR(axisNumber, vNegLogical); logicalNegValid = !logicalNeg.IsNaN && vNegLogical != vMeanLogical; } } break; case ValueInterpretation.AbsoluteValue: { if (posErrCol != null) { var vPosLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(posErrCol[originalRowIndex]); vPosLogical = Calc.RMath.ClampToInterval(vPosLogical, logicalClampMinimum, logicalClampMaximum); logicalPos.SetR(axisNumber, vPosLogical); logicalPosValid = !logicalPos.IsNaN && vPosLogical != vMeanLogical; } if (negErrCol != null) { var vNegLogical = layer.Scales[axisNumber].PhysicalVariantToNormal(negErrCol[originalRowIndex]); vNegLogical = Calc.RMath.ClampToInterval(vNegLogical, logicalClampMinimum, logicalClampMaximum); logicalNeg.SetR(axisNumber, vNegLogical); logicalNegValid = !logicalNeg.IsNaN && vNegLogical != vMeanLogical; } if (object.ReferenceEquals(negErrCol, posErrCol)) { logicalNegValid = false; // then we need only to plot the positive column, since both colums are identical } } break; } // end switch if (!(logicalPosValid || logicalNegValid)) continue; // nothing to do for this point if both pos and neg logical point are invalid. if (logicalNegValid) { errorBarPath.Reset(); layer.CoordinateSystem.GetIsoline(errorBarPath, logicalMean, logicalNeg); PointF[] shortenedPathPoints = null; bool shortenedPathPointsCalculated = false; if (_useSymbolGap) { double gap = _symbolGapOffset + _symbolGapFactor * symbolSize; if (gap > 0) { errorBarPath.Flatten(); var pathPoints = errorBarPath.PathPoints; shortenedPathPoints = GdiExtensionMethods.ShortenedBy(pathPoints, RADouble.NewAbs(gap / 2), RADouble.NewAbs(0)); shortenedPathPointsCalculated = true; if (null == shortenedPathPoints && _forceVisibilityOfEndCap && !(strokePen.EndCap is Altaxo.Graph.Gdi.LineCaps.FlatCap)) { var totalLineLength = GdiExtensionMethods.TotalLineLength(pathPoints); var shortTheLineBy = Math.Max(0, totalLineLength - 0.125 * strokePen.Width); shortenedPathPoints = GdiExtensionMethods.ShortenedBy(pathPoints, RADouble.NewAbs(shortTheLineBy), RADouble.NewAbs(0)); } } } if (shortenedPathPointsCalculated) { if (null != shortenedPathPoints) { g.DrawLines(strokePen, shortenedPathPoints); } } else { g.DrawPath(strokePen, errorBarPath); } } if (logicalPosValid) { errorBarPath.Reset(); layer.CoordinateSystem.GetIsoline(errorBarPath, logicalMean, logicalPos); PointF[] shortenedPathPoints = null; bool shortenedPathPointsCalculated = false; if (_useSymbolGap) { double gap = _symbolGapOffset + _symbolGapFactor * symbolSize; if (gap > 0) { errorBarPath.Flatten(); var pathPoints = errorBarPath.PathPoints; shortenedPathPoints = GdiExtensionMethods.ShortenedBy(pathPoints, RADouble.NewAbs(gap / 2), RADouble.NewAbs(0)); shortenedPathPointsCalculated = true; if (null == shortenedPathPoints && _forceVisibilityOfEndCap && !(strokePen.EndCap is Altaxo.Graph.Gdi.LineCaps.FlatCap)) { var totalLineLength = GdiExtensionMethods.TotalLineLength(pathPoints); var shortTheLineBy = Math.Max(0, totalLineLength - 0.125 * strokePen.Width); shortenedPathPoints = GdiExtensionMethods.ShortenedBy(pathPoints, RADouble.NewAbs(shortTheLineBy), RADouble.NewAbs(0)); } } } if (shortenedPathPointsCalculated) { if (null != shortenedPathPoints) { g.DrawLines(strokePen, shortenedPathPoints); } } else { g.DrawPath(strokePen, errorBarPath); } } } g.Clip = oldClippingRegion; }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { string S = ""; DA.GetData(0, ref S); string fontString = ""; DA.GetData(1, ref fontString); bool close = false; DA.GetData(2, ref close); double size = 0.0; DA.GetData(3, ref size); double precision = 0.0; DA.GetData(4, ref precision); Plane basePlane = new Plane(); DA.GetData(5, ref basePlane); int J = 0; DA.GetData(6, ref J); float fS = size == 0 ? 1 : (float)size; Font local_font = new Font(fontString, (float)fS); System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath(); path.AddString(S, local_font.FontFamily, (int)local_font.Style, local_font.Size, new PointF(0, 0), new StringFormat()); System.Drawing.Drawing2D.Matrix matrix = new System.Drawing.Drawing2D.Matrix(); // transformation matrix matrix.Reset(); // build identity matrix // __________________ autoList part __________________ // variable for the list Grasshopper.Kernel.Special.GH_ValueList vList; // tries to cast input as list try { // if the list is not the first parameter then change Input[6] to the corresponding value vList = Params.Input[6].Sources[0] as Grasshopper.Kernel.Special.GH_ValueList; // check if the list must be created if (!vList.NickName.Equals("Justification")) { vList.ClearData(); vList.ListItems.Clear(); vList.NickName = "Justification"; for (int i = 0; i < justification.Length; i++) { vList.ListItems.Add(new Grasshopper.Kernel.Special.GH_ValueListItem(justification[i][0], justification[i][1])); } //var item1 = new Grasshopper.Kernel.Special.GH_ValueListItem("TopLeft", "0"); //var item2 = new Grasshopper.Kernel.Special.GH_ValueListItem("MiddleLeft", "1"); //var item3 = new Grasshopper.Kernel.Special.GH_ValueListItem("BottomLeft", "2"); //var item4 = new Grasshopper.Kernel.Special.GH_ValueListItem("TopCenter", "3"); //var item5 = new Grasshopper.Kernel.Special.GH_ValueListItem("MiddleCenter", "4"); //var item6 = new Grasshopper.Kernel.Special.GH_ValueListItem("BottomCenter", "5"); //var item7 = new Grasshopper.Kernel.Special.GH_ValueListItem("TopRight", "6"); //var item8 = new Grasshopper.Kernel.Special.GH_ValueListItem("MiddleRight", "7"); //var item9 = new Grasshopper.Kernel.Special.GH_ValueListItem("BottomRight", "8"); //vList.ListItems.Add(item1); //vList.ListItems.Add(item2); //vList.ListItems.Add(item3); //vList.ListItems.Add(item4); //vList.ListItems.Add(item5); //vList.ListItems.Add(item6); //vList.ListItems.Add(item7); //vList.ListItems.Add(item8); //vList.ListItems.Add(item9); vList.ListItems[0].Value.CastTo(out J); } } catch { // handles anything that is not a value list } // ______________ text justification ______________ RectangleF rec = path.GetBounds(); // bounding rectangle for text float dX = Convert.ToSingle(rec.Width * -0.5), dY = Convert.ToSingle(rec.Height * 0.5); switch (J) { case 0: // top left dX = 0; dY = fS; break; case 1: // middle left dX = 0; dY = Convert.ToSingle((-rec.Height) * 0.5 + fS); break; case 2: // bottom left dX = 0; dY = Convert.ToSingle(-rec.Height + fS * 0.5); break; case 3: // top center dX = Convert.ToSingle(rec.Width * -0.5); dY = fS; break; case 4: // middle center dX = Convert.ToSingle(rec.Width * -0.5); dY = Convert.ToSingle((-rec.Height) * 0.5 + fS); break; case 5: // bottom center dX = Convert.ToSingle(rec.Width * -0.5); dY = Convert.ToSingle(-rec.Height + fS * 0.5); break; case 6: // top right dX = Convert.ToSingle(rec.Width * -1); dY = fS; break; case 7: // middle right dX = Convert.ToSingle(rec.Width * -1); dY = Convert.ToSingle((-rec.Height) * 0.5 + fS); break; case 8: // bottom right dX = Convert.ToSingle(rec.Width * -1); dY = Convert.ToSingle(-rec.Height + fS * 0.5); break; } //float dX = Convert.ToSingle(rec.Width * -0.5); //float dY = Convert.ToSingle(rec.Height * 0.5); System.Drawing.Drawing2D.Matrix mTrans = new System.Drawing.Drawing2D.Matrix(1, 0, 0, 1, dX, dY); // build transformation matrix path.Transform(mTrans); // transform text path // ______________ convert to polylines ______________ path.Flatten(matrix, (float)(size / precision)); // turns the path into a polyline that approximates the path PointF[] pts = path.PathPoints; // get path points Byte[] tps = path.PathTypes; // get path point types List <Polyline> strokes = new List <Polyline>(); // List for strokes Polyline stroke = new Polyline(); Byte typ_start = Convert.ToByte(System.Drawing.Drawing2D.PathPointType.Start);// find start points condition // the conversion loop for (int i = 0; i < pts.Length; i++) { // if a start point is found, and the existing polyline is not null nor a single point, // add polyline to the strokes and create a new polyline if (tps[i] == typ_start) { if (stroke != null && stroke.Count > 1) { if (close && !stroke.IsClosed) { stroke.Add(stroke[0]); // close polyline if necessary } strokes.Add(stroke); } stroke = new Polyline(); } // in any other case add the next point to a polyline stroke.Add(pts[i].X, -pts[i].Y + size, 0); // add last stroke to the list if (i == pts.Length - 1) { if (close && !stroke.IsClosed) { stroke.Add(stroke[0]); // and close it if necessary } strokes.Add(stroke); } } // ______________ align strokes to given plane ______________ Transform align = Transform.PlaneToPlane(Plane.WorldXY, basePlane); // align transformation for (int j = 0; j < strokes.Count; j++) { strokes[j].Transform(align); } DA.SetDataList(0, strokes); }