Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version

3D Pie Chart

, 13 Mar 2006
A class library for drawing 3D pie charts.
using System;
using System.Diagnostics;
using System.Drawing.Drawing2D;

namespace System.Drawing {
	/// <summary>
	///  Quadrilateral object.
	/// </summary>
	public class Quadrilateral : IDisposable {
        /// <summary>
        ///   Creates empty <c>Quadrilateral</c> object
        /// </summary>
        protected Quadrilateral() {
		}

        /// <summary>
        ///   Initilizes <c>Quadrilateral</c> object with given corner points.
        /// </summary>
        /// <param name="point1">
        ///   First <c>PointF</c>.
        /// </param>
        /// <param name="point2">
        ///   Second <c>PointF</c>.
        /// </param>
        /// <param name="point3">
        ///   Third <c>PointF</c>.
        /// </param>
        /// <param name="point4">
        ///   Fourth <c>PointF</c>.
        /// </param>
        /// <param name="toClose">
        ///   Indicator should the quadrilateral be closed by the line.
        /// </param>
        public Quadrilateral(PointF point1, PointF point2, PointF point3, PointF point4, bool toClose) {
            byte[] pointTypes = (byte[])s_quadrilateralPointTypes.Clone();
            if (toClose)
                pointTypes[3] |= (byte)PathPointType.CloseSubpath;
            m_path = new GraphicsPath(new PointF[] { point1, point2, point3, point4 }, pointTypes);
        }

        /// <summary>
        ///   <c>Finalize</c> method.
        /// </summary>
        ~Quadrilateral() {
            Dispose(false);
        }

        /// <summary>
        ///   Implementation of <c>IDisposable</c> interface.
        /// </summary>
        public void Dispose() {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        ///   Disposes of all pie slices.
        /// </summary>
        protected virtual void Dispose(bool disposing) {
            if (!m_disposed) {
                if (disposing) {
                    m_path.Dispose();
                }
                m_disposed = true;
            }
        }

        /// <summary>
        ///   Draws the <c>Quadrilateral</c> with <c>Graphics</c> provided.
        /// </summary>
        /// <param name="graphics">
        ///   <c>Graphics</c> used to draw.
        /// </param>
        /// <param name="pen">
        ///   <c>Pen</c> used to draw outline.
        /// </param>
        /// <param name="brush">
        ///   <c>Brush</c> used to fill the inside. 
        /// </param>
        public void Draw(Graphics graphics, Pen pen, Brush brush) {
            graphics.FillPath(brush, m_path);
            graphics.DrawPath(pen, m_path);
        }

        /// <summary>
        ///   Checks if the given <c>PointF</c> is contained within the 
        ///   quadrilateral.
        /// </summary>
        /// <param name="point">
        ///   <c>PointF</c> structure to check for.
        /// </param>
        /// <returns>
        ///   <c>true</c> if the point is contained within the quadrilateral.
        /// </returns>
        public bool Contains(PointF point) {
            if (m_path.PointCount == 0 || m_path.PathPoints.Length == 0)
                return false;
            return Contains(point, m_path.PathPoints);
        }

        /// <summary>
        ///   Checks if given <c>PointF</c> is contained within quadrilateral
        ///   defined by <c>cornerPoints</c> provided.
        /// </summary>
        /// <param name="point">
        ///   <c>PointF</c> to check.
        /// </param>
        /// <param name="cornerPoints">
        ///   Array of <c>PointF</c> structures defining corners of the
        ///   quadrilateral.
        /// </param>
        /// <returns>
        ///   <c>true</c> if the point is contained within the quadrilateral.
        /// </returns>
        public static bool Contains(PointF point, PointF[] cornerPoints) {
            int intersections = 0;
            for (int i = 1; i < cornerPoints.Length; ++i) {
                if (DoesIntersect(point, cornerPoints[i], cornerPoints[i - 1]))
                    ++intersections;
            }
            if (DoesIntersect(point, cornerPoints[cornerPoints.Length - 1], cornerPoints[0]))
                ++intersections;
            return (intersections % 2 != 0);
        }

        /// <summary>
        ///   Checks if the line coming out of the <c>point</c> downwards 
        ///   intersects with a line through <c>point1</c> and <c>point2</c>.
        /// </summary>
        /// <param name="point">
        ///   <c>PointF</c> from which vertical line is drawn downwards.
        /// </param>
        /// <param name="point1">
        ///   First <c>PointF</c> through which line is drawn.
        /// </param>
        /// <param name="point2">
        ///   Second <c>PointF</c> through which line is drawn.
        /// </param>
        /// <returns>
        ///   <c>true</c> if lines intersect.
        /// </returns>
        private static bool DoesIntersect(PointF point, PointF point1, PointF point2) {
            float x2 = point2.X;
            float y2 = point2.Y;
            float x1 = point1.X;
            float y1 = point1.Y;
            if ((x2 < point.X && x1 >= point.X) || (x2 >= point.X && x1 < point.X)) {
                float y = (y2 - y1) / (x2 - x1) * (point.X - x1) + y1;
                return y > point.Y;
            }
            return false;
        }

        /// <summary>
        ///   <c>GraphicsPath</c> representing the quadrilateral.
        /// </summary>
        private GraphicsPath m_path = new GraphicsPath();

        private bool m_disposed = false;

        /// <summary>
        ///   <c>PathPointType</c>s decribing the <c>GraphicsPath</c> points.
        /// </summary>
        private static byte[] s_quadrilateralPointTypes = new byte[]  {   
                                                                          (byte)PathPointType.Start,
                                                                          (byte)PathPointType.Line,
                                                                          (byte)PathPointType.Line,
                                                                          (byte)PathPointType.Line | (byte)PathPointType.CloseSubpath 
                                                                      };
        
        public static readonly Quadrilateral Empty = new Quadrilateral();
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The zlib/libpng License

Share

About the Author

Julijan Sribar
Software Developer (Senior) Syntellect
Croatia Croatia
Graduated at the Faculty of Electrical Engineering and Computing, University of Zagreb (Croatia) and received M.Sc. degree in electronics. For several years he was research and lecturing assistant in the fields of solid state electronics and electronic circuits, published several scientific and professional papers, as well as a book "Physics of Semiconductor Devices - Solved Problems with Theory" (in Croatian).
During that work he gained interest in C++ programming language and have co-written "C++ Demystified" (in Croatian), 1st edition published in 1997, 2nd in 2001, 3rd in 2010.
After book publication, completely switched to software development, programming mostly in C++ and in C#.
Follow on   LinkedIn

| Advertise | Privacy | Mobile
Web04 | 2.8.140902.1 | Last Updated 13 Mar 2006
Article Copyright 2004 by Julijan Sribar
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid