bool ZedGraphControl_MouseMoveEvent( ZedGraph.ZedGraphControl sender, MouseEventArgs e ) { if( CurrentGraphForm == null || !peakIntegrationMode.Checked || !CurrentGraphForm.ZedGraphControl.Focused ) return false; if( integratePeaksLine != null && e.Button == MouseButtons.Left ) { double x = CurrentGraphForm.ZedGraphControl.GraphPane.XAxis.Scale.ReverseTransform( (float) e.X ); double y = CurrentGraphForm.ZedGraphControl.GraphPane.YAxis.Scale.ReverseTransform( (float) e.Y ); //CurrentGraphForm.ZedGraphControl.GraphPane.GraphObjList.Remove( integratePeaksLine ); //integratePeaksLine = new ZedGraph.LineItem( integratePeaksLine.Location.X1, integratePeaksLine.Location.Y1, x, y ); //integratePeaksLine.Location.CoordinateFrame = ZedGraph.CoordType.AxisXYScale; //CurrentGraphForm.ZedGraphControl.GraphPane.GraphObjList.Add( integratePeaksLine ); integratePeaksLine.Points[1].X = Math.Min( CurrentGraphForm.ZedGraphControl.GraphPane.XAxis.Scale.Max, Math.Max( CurrentGraphForm.ZedGraphControl.GraphPane.XAxis.Scale.Min, x ) ); integratePeaksLine.Points[1].Y = Math.Min( CurrentGraphForm.ZedGraphControl.GraphPane.YAxis.Scale.Max, Math.Max( CurrentGraphForm.ZedGraphControl.GraphPane.YAxis.Scale.Min, y ) ); if( CurrentGraphForm.ZedGraphControl.GraphPane.CurveList[0].Points is PointList ) { foreach( ZedGraph.PolyObj obj in integratePeaksAreas ) CurrentGraphForm.ZedGraphControl.GraphPane.GraphObjList.Remove( obj ); integratePeaksAreas.Clear(); PointList pointList = (PointList) CurrentGraphForm.ZedGraphControl.GraphPane.CurveList[0].Points; if( pointList.ScaledCount == 0 ) return false; double x1, y1, x2, y2; if( integratePeaksLine.Points[0].X > integratePeaksLine.Points[1].X ) { x1 = integratePeaksLine.Points[1].X; y1 = integratePeaksLine.Points[1].Y; x2 = integratePeaksLine.Points[0].X; y2 = integratePeaksLine.Points[0].Y; } else { x1 = integratePeaksLine.Points[0].X; y1 = integratePeaksLine.Points[0].Y; x2 = integratePeaksLine.Points[1].X; y2 = integratePeaksLine.Points[1].Y; } int lowerBoundIndex = pointList.LowerBound( x1 ); int upperBoundIndex = pointList.LowerBound( x2 ); if( upperBoundIndex < 0 ) upperBoundIndex = pointList.ScaledCount - 1; double totalIntegratedArea = 0.0; int totalAreaPoints = 0; int totalAreaCount = 0; // integration line can be in any of these states: // * entirely to the left of the curve: // - no integration // * entirely to the right of the curve: // - no integration // * entirely between two consecutive points: // - integration is entirely interpolated based on data slope // * starts to the left of the curve and ends between two consecutive points: // - start integration at the X value of the first data point // - end integration at the line's right X value // * starts between two consecutive points and ends to the right of the curve: // - start integration at the line's left X value // - end integration at the X value of the last data point // * starts between two consecutive points and ends between two different consecutive points: // - start integration at the line's left X value // - end integration at the line's right X value // * entirely above the curve: // - no integration // * starts above the curve and ends below the curve: // - start integration at the first intersection of the line with the curve // - end integration at the X value where the line ends // * starts below the curve and ends above the curve: // - start integration at the X value where the line starts // - end integration at the last intersection of the line with the curve // * entirely below the curve: // - start and end integration at the X values of the line // * the Y value of the line's start point is less than 0 and the end point's is not: // - a special area point must be added before the first area's bottom left point // - add it at the intersection of the line with the X axis // * the Y value of the line's end point is less than 0 and the start point's is not: // - a special area point must be added after the last area's bottom right point // - add it at the intersection of the line with the X axis // * the Y values of both the start and end points of the line are less than 0: // - no special points are necessary if( lowerBoundIndex >= 0 && x2 > x1 ) { // calculate the linear function for integration line double integratePeaksLineA = ( y2 - y1 ) / ( x2 - x1 ); double integratePeaksLineB = y1 - ( integratePeaksLineA * x1 ); // restrict the X range of the integration line to the minimum and maximum X values of the curve // interpolate the Y value of the integration line at those X values double leftInterpolatedX = Math.Max( pointList.ScaledList[0].X, x1 ); double leftInterpolatedY = Math.Max( 0, integratePeaksLineA * leftInterpolatedX + integratePeaksLineB ); double rightInterpolatedX = Math.Min( pointList.ScaledList[pointList.ScaledCount - 1].X, x2 ); double rightInterpolatedY = Math.Max( 0, integratePeaksLineA * rightInterpolatedX + integratePeaksLineB ); List<ZedGraph.PointD> areaPoints = new List<ZedGraph.PointD>(); //List<List<ZedGraph.PointD>> areaTrapezoids = new List<List<ZedGraph.PointD>>(); for( int i = Math.Max( 1, lowerBoundIndex ); i <= upperBoundIndex; ++i ) { ZedGraph.PointPair rightPoint = pointList.ScaledList[i]; ZedGraph.PointPair leftPoint = pointList.ScaledList[i - 1]; // interpolate the Y value of the integration line at the previous and current points' X value double lastPointLineY = integratePeaksLineA * leftPoint.X + integratePeaksLineB; double curPointLineY = integratePeaksLineA * rightPoint.X + integratePeaksLineB; // calculate the linear function between the previous and current points double dataA = ( rightPoint.Y - leftPoint.Y ) / ( rightPoint.X - leftPoint.X ); double dataB = rightPoint.Y - ( dataA * rightPoint.X ); double leftInterpolatedPointY = dataA * leftInterpolatedX + dataB; double rightInterpolatedPointY = dataA * rightInterpolatedX + dataB; bool leftInterpolatedPointIsAboveLine = ( leftInterpolatedPointY >= leftInterpolatedY ); bool rightInterpolatedPointIsAboveLine = ( rightInterpolatedPointY >= rightInterpolatedY ); bool leftPointIsAboveLine = ( leftPoint.Y > lastPointLineY ); bool rightPointIsAboveLine = ( rightPoint.Y > curPointLineY ); bool leftPointIsLowerBound = ( i == 1 || i == lowerBoundIndex ); bool rightPointIsUpperBound = ( i == upperBoundIndex ); if( !leftInterpolatedPointIsAboveLine && !rightInterpolatedPointIsAboveLine || !leftPointIsAboveLine && !rightPointIsAboveLine ) continue; bool needIntersection = ( leftInterpolatedPointIsAboveLine != rightInterpolatedPointIsAboveLine ); bool areaIsEmpty = ( areaPoints.Count == 0 ); if( rightPointIsAboveLine || leftPointIsAboveLine ) { if( areaIsEmpty ) // start a new area { if( leftPointIsLowerBound && leftInterpolatedPointIsAboveLine ) // interpolate the point on the curve above the line { if( y1 <= 0 && y2 > 0 ) { double croppedBottomX = -integratePeaksLineB / integratePeaksLineA; if( croppedBottomX != leftInterpolatedX ) areaPoints.Add( new ZedGraph.PointD( croppedBottomX, 0 ) ); } areaPoints.Add( new ZedGraph.PointD( leftInterpolatedX, leftInterpolatedY ) ); // bottom left areaPoints.Add( new ZedGraph.PointD( leftInterpolatedX, leftInterpolatedPointY ) ); // top left } else if( needIntersection ) // interpolate the intersection of line and curve { double intersectX = ( dataB - integratePeaksLineB ) / ( integratePeaksLineA - dataA ); double intersectY = dataA * intersectX + dataB; areaPoints.Add( new ZedGraph.PointD( intersectX, intersectY ) ); } } if( rightPointIsUpperBound ) // end at the upper bound and add current area to the area list { if( rightInterpolatedPointIsAboveLine ) { // add a new point to the current area //areaPoints.Add( new ZedGraph.PointD( pointList.ScaledList[i].X, pointList.ScaledList[i].Y ) ); areaPoints.Add( new ZedGraph.PointD( rightInterpolatedX, rightInterpolatedPointY ) ); // top right areaPoints.Add( new ZedGraph.PointD( rightInterpolatedX, rightInterpolatedY ) ); // bottom right if( y2 <= 0 && y1 > 0 ) // add another point if line extends below X axis { double croppedBottomX = -integratePeaksLineB / integratePeaksLineA; if( croppedBottomX != rightInterpolatedX ) areaPoints.Add( new ZedGraph.PointD( croppedBottomX, 0 ) ); } } else if( needIntersection ) // interpolate the intersection of line and curve { double intersectX = ( dataB - integratePeaksLineB ) / ( integratePeaksLineA - dataA ); double intersectY = dataA * intersectX + dataB; areaPoints.Add( new ZedGraph.PointD( intersectX, intersectY ) ); } if( areaPoints.Count == 0 ) continue; ZedGraph.PolyObj integratePeaksArea = new ZedGraph.PolyObj( areaPoints.ToArray(), Color.Black, Color.Cyan, Color.Cyan ); integratePeaksArea.Location.CoordinateFrame = ZedGraph.CoordType.AxisXYScale; //integratePeaksArea.IsClosedFigure = true; areaPoints.Add( areaPoints[0] ); integratePeaksAreas.Add( integratePeaksArea ); double currentIntegratedArea = 0.0; for( int k, j = 0; j < areaPoints.Count; ++j ) { k = ( j + 1 ) % areaPoints.Count; currentIntegratedArea += areaPoints[j].X * areaPoints[k].Y; currentIntegratedArea -= areaPoints[j].Y * areaPoints[k].X; } totalIntegratedArea += Math.Abs( currentIntegratedArea / 2.0 ); totalAreaPoints += areaPoints.Count - 1; ++totalAreaCount; areaPoints.Clear(); } else { // add a new top right point to the current area areaPoints.Add( new ZedGraph.PointD( pointList.ScaledList[i].X, pointList.ScaledList[i].Y ) ); } } if( !rightPointIsAboveLine && !rightPointIsUpperBound )// close the current area and add it to the area list { double intersectX = ( dataB - integratePeaksLineB ) / ( integratePeaksLineA - dataA ); double intersectY = dataA * intersectX + dataB; areaPoints.Add( new ZedGraph.PointD( intersectX, intersectY ) ); if( areaPoints.Count == 0 ) continue; ZedGraph.PolyObj integratePeaksArea = new ZedGraph.PolyObj( areaPoints.ToArray(), Color.Black, Color.Cyan, Color.Cyan ); integratePeaksArea.Location.CoordinateFrame = ZedGraph.CoordType.AxisXYScale; //integratePeaksArea.IsClosedFigure = true; areaPoints.Add( areaPoints[0] ); integratePeaksAreas.Add( integratePeaksArea ); double currentIntegratedArea = 0.0; for( int k, j = 0; j < areaPoints.Count; ++j ) { k = ( j + 1 ) % areaPoints.Count; currentIntegratedArea += areaPoints[j].X * areaPoints[k].Y; currentIntegratedArea -= areaPoints[j].Y * areaPoints[k].X; } totalIntegratedArea += Math.Abs( currentIntegratedArea / 2.0 ); totalAreaPoints += areaPoints.Count - 1; ++totalAreaCount; areaPoints.Clear(); } } /*if( areaPoints.Count > 2 ) { List<ZedGraph.PointD> areaTrapezoid = new List<ZedGraph.PointD>(); areaTrapezoid.Add( areaPoints[areaPoints.Count - 3] ); // top left areaTrapezoid.Add( areaPoints[areaPoints.Count - 2] ); // top right areaTrapezoid.Add( areaPoints[areaPoints.Count - 1] ); // bottom right // bottom left double bottomLeftY = Math.Max( 0, integratePeaksLineA * areaPoints[areaPoints.Count - 3].X + integratePeaksLineB ); areaTrapezoid.Add( new ZedGraph.PointD( areaPoints[areaPoints.Count - 3].X, bottomLeftY ) ); areaTrapezoids.Add( areaTrapezoid ); }*/ /*foreach( List<ZedGraph.PointD> trapezoidPoints in areaTrapezoids ) { ZedGraph.PolyObj trapezoid = new ZedGraph.PolyObj( trapezoidPoints.ToArray(), Color.Black, Color.Green, Color.Green ); trapezoid.Location.CoordinateFrame = ZedGraph.CoordType.AxisXYScale; trapezoid.IsClosedFigure = true; integratePeaksAreas.Add( trapezoid ); }*/ foreach( ZedGraph.PolyObj obj in integratePeaksAreas ) CurrentGraphForm.ZedGraphControl.GraphPane.GraphObjList.Add( obj ); //CurrentGraphForm.ZedGraphControl.GraphPane.Title.Text = totalIntegratedArea.ToString("f0") + " " + totalAreaPoints + " " + totalAreaCount; //CurrentGraphForm.ZedGraphControl.GraphPane.Title.IsVisible = true; CurrentGraphForm.CurrentGraphItem.TotalIntegratedArea = totalIntegratedArea; //int currentIndex = scanNumberComboBox.SelectedIndex; //object currentObject = scanNumberComboBox.SelectedItem; //scanNumberComboBox.Items.RemoveAt( currentIndex ); //scanNumberComboBox.Items.Insert( currentIndex, currentObject ); } } CurrentGraphForm.ZedGraphControl.Refresh(); return false; } return true; }
private void DesenhaPerfil() { zedPerfil.GraphPane.CurveList.Clear(); zedPerfil.GraphPane.GraphObjList.Clear(); double h = (double)numH.Value; double[] sols = AreaPerimeter.Solve(lstProfile, h); if (sols.Length % 2 == 0) { double[] start = new double[sols.Length >> 1]; double[] stop = new double[sols.Length >> 1]; double totalLength = 0; for (int k = 0; k < sols.Length; k += 2) { start[k >> 1] = sols[k]; stop[k >> 1] = sols[k + 1]; totalLength += sols[k + 1] - sols[k]; double[] xx = new double[] { sols[k], sols[k + 1] }; double[] yy = new double[] { h, h }; //ZedGraph.LineItem li3 = zedPerfil.GraphPane.AddCurve(k == 0 ? "Nível de água" : "", xx, yy, Color.LightBlue, ZedGraph.SymbolType.None); ZedGraph.LineItem li3 = zedPerfil.GraphPane.AddCurve(k == 0 ? "Water level" : "", xx, yy, Color.LightBlue, ZedGraph.SymbolType.None); li3.Line.Width = 3; } double p2; double area = AreaPerimeter.GetArea(lstProfile, h, start, stop, out p2); lblArea.Text = Math.Round(area, 3).ToString(); lblPerim.Text = Math.Round(p2, 3).ToString(); lblSurfLen.Text = Math.Round(totalLength, 3).ToString(); } #region Graficos double[] x = lstProfile.Keys.ToArray(); double[] y = lstProfile.Values.ToArray(); ZedGraph.LineItem li = zedPerfil.GraphPane.AddCurve("", x, y, Color.SandyBrown); li.Line.Width = 3; double[] xNivel = new double[] { 10, 20 }; double[] yNivel = new double[] { -1, -1 }; //ZedGraph.LineItem li2 = zedPerfil.GraphPane.AddCurve("", xNivel, yNivel, Color.LightBlue); //, ZedGraph.SymbolType.None); //li2.Line.Fill = new ZedGraph.Fill(Color.Blue, Color.Blue, 45F); List <ZedGraph.PointD> lstPt = new List <ZedGraph.PointD>(); lstPt.Add(new ZedGraph.PointD(2, -1)); lstPt.Add(new ZedGraph.PointD(8, -1)); lstPt.Add(new ZedGraph.PointD(9, -3)); lstPt.Add(new ZedGraph.PointD(0, -3.5)); ZedGraph.PolyObj pObj = new ZedGraph.PolyObj(lstPt.ToArray(), Color.LightBlue, Color.Blue, Color.Blue); //zedPerfil.GraphPane.GraphObjList.Add(pObj); zedPerfil.AxisChange(); zedPerfil.Refresh(); #endregion }