This shows you the differences between two versions of the page.
| en:software:arm-can:drivers:polygon [2010/06/06 14:35] – created mikk.leini | en:software:arm-can:drivers:polygon [2020/07/20 12:00] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== StellarisWare Graphics Library Polygon ====== | ||
| + | |||
| + | ===== polygon.c ===== | ||
| + | |||
| + | <code c> | ||
| + | // | ||
| + | // | ||
| + | // polygon.c - Routines for drawing and filling polygons. | ||
| + | // | ||
| + | // | ||
| + | // Copyright (c) 2010 Mikk Leini, TUT Robotics Club NPO | ||
| + | // | ||
| + | // Polygon fill algorithm is based on Darel Rex Finley suggestions: | ||
| + | // | ||
| + | // | ||
| + | // | ||
| + | |||
| + | #include " | ||
| + | #include " | ||
| + | |||
| + | // | ||
| + | // | ||
| + | //! \addtogroup primitives_api | ||
| + | //! @{ | ||
| + | // | ||
| + | // | ||
| + | |||
| + | // | ||
| + | // | ||
| + | //! Draws a polygon. | ||
| + | //! | ||
| + | //! \param pContext is a pointer to the drawing context to use. | ||
| + | //! \param pRect is a pointer to the array of structures containing the points | ||
| + | //! of the polygon. | ||
| + | //! \param ulNumPoints is a number of points in array. | ||
| + | //! \param bClosedLoop indicates wheter to draw line between the first and | ||
| + | //! the last point. | ||
| + | //! | ||
| + | //! This function draws lines between the consecutive points and if requiered | ||
| + | //! the line between the first and the last point. | ||
| + | //! | ||
| + | //! \return None. | ||
| + | // | ||
| + | // | ||
| + | void | ||
| + | GrPolyDraw(const tContext *pContext, const tPoint *pPoints, | ||
| + | | ||
| + | { | ||
| + | unsigned long ulIdx; | ||
| + | |||
| + | // | ||
| + | // Check the arguments. | ||
| + | // | ||
| + | ASSERT(pContext); | ||
| + | ASSERT(pPoints); | ||
| + | ASSERT(sNumPoints > (bClosedLoop ? 2 : 1)); | ||
| + | |||
| + | // | ||
| + | // Draw the lines between points | ||
| + | // | ||
| + | for(ulIdx = 0; ulIdx < ulNumPoints - 1; ulIdx++) | ||
| + | { | ||
| + | GrLineDraw(pContext, | ||
| + | | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // Draw a closing line between first and last point? | ||
| + | // | ||
| + | if(ucClosedLoop) | ||
| + | { | ||
| + | GrLineDraw(pContext, | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // | ||
| + | //! Draws a filled polygon. | ||
| + | //! | ||
| + | //! \param pContext is a pointer to the drawing context to use. | ||
| + | //! \param pRect is a pointer to the array of structures containing the points | ||
| + | //! of the polygon. | ||
| + | //! \param ulNumPoints is a number of points in array. | ||
| + | //! | ||
| + | //! This function fills a polygon specified by the consecutive points. | ||
| + | //! | ||
| + | //! The clipping of the polygon to the clipping rectangle is performed within | ||
| + | //! this routine; | ||
| + | //! | ||
| + | //! \return None. | ||
| + | // | ||
| + | // | ||
| + | void | ||
| + | GrPolyFill(const tContext *pContext, const tPoint *pPoints, | ||
| + | | ||
| + | { | ||
| + | unsigned long ulIdx, ulIdx2; | ||
| + | unsigned long ulNumNodes; | ||
| + | short sY; | ||
| + | short pNodeList[100]; | ||
| + | short sSwap; | ||
| + | |||
| + | // | ||
| + | // Check the arguments. | ||
| + | // | ||
| + | ASSERT(pContext); | ||
| + | ASSERT(pPoints); | ||
| + | | ||
| + | |||
| + | // | ||
| + | // Loop through the rows of the clipping area. | ||
| + | // | ||
| + | for(sY = pContext-> | ||
| + | { | ||
| + | // | ||
| + | // Build a list of nodes. | ||
| + | // | ||
| + | ulNumNodes = 0; | ||
| + | |||
| + | // | ||
| + | // Search for X coordinates of polygons on the current row. | ||
| + | // | ||
| + | for(ulIdx = 0; ulIdx < ulNumPoints; | ||
| + | { | ||
| + | // | ||
| + | // Get the index of next point and wrap around points count. | ||
| + | // | ||
| + | ulIdx2 = (ulIdx + 1) % ulNumPoints; | ||
| + | |||
| + | // | ||
| + | // Check if the polygon line exists on the same row. | ||
| + | // | ||
| + | if(((pPoints[ulIdx].sY < sY) && (pPoints[ulIdx2].sY >= sY)) || | ||
| + | | ||
| + | { | ||
| + | // | ||
| + | // Make sure nodes list isn't overflowed. | ||
| + | // | ||
| + | if(ulNumNodes >= 100) break; | ||
| + | |||
| + | // | ||
| + | // Calculate the intersection point X coordinate | ||
| + | // of the polygon edge. | ||
| + | // | ||
| + | pNodeList[ulNumNodes++] = | ||
| + | (pPoints[ulIdx].sX + (sY - pPoints[ulIdx].sY) * | ||
| + | (pPoints[ulIdx2].sX - pPoints[ulIdx].sX) / | ||
| + | (pPoints[ulIdx2].sY - pPoints[ulIdx].sY)); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // Sort the nodes, via a simple “Bubble” sort. | ||
| + | // | ||
| + | ulIdx = 0; | ||
| + | |||
| + | while(ulIdx + 1 < ulNumNodes) | ||
| + | { | ||
| + | if(pNodeList[ulIdx] > pNodeList[ulIdx + 1]) | ||
| + | { | ||
| + | sSwap = pNodeList[ulIdx]; | ||
| + | pNodeList[ulIdx] = pNodeList[ulIdx + 1]; | ||
| + | pNodeList[ulIdx + 1] = sSwap; | ||
| + | |||
| + | if(ulIdx) | ||
| + | { | ||
| + | ulIdx--; | ||
| + | } | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | ulIdx++; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // Fill the pixels between node pairs. | ||
| + | // | ||
| + | for(ulIdx = 0; ulIdx < ulNumNodes; ulIdx += 2) | ||
| + | { | ||
| + | // | ||
| + | // Break when lines go out of clipping region. | ||
| + | // | ||
| + | if(pNodeList[ulIdx] > pContext-> | ||
| + | |||
| + | // | ||
| + | // Skip when line ends before clipping region. | ||
| + | // | ||
| + | if(pNodeList[ulIdx + 1] < pContext-> | ||
| + | |||
| + | // | ||
| + | // Clip the line from left. | ||
| + | // | ||
| + | if(pNodeList[ulIdx] < pContext-> | ||
| + | { | ||
| + | pNodeList[ulIdx] = pContext-> | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // Clip the line from right. | ||
| + | // | ||
| + | if(pNodeList[ulIdx + 1] > pContext-> | ||
| + | { | ||
| + | pNodeList[ulIdx + 1] = pContext-> | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // Call the low level horizontal line drawing routine. | ||
| + | // | ||
| + | DpyLineDrawH(pContext-> | ||
| + | | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // | ||
| + | //! Draws a triangle. | ||
| + | //! | ||
| + | //! \param pContext is a pointer to the drawing context to use. | ||
| + | //! \param pPoint1 is a pointer to the first point. | ||
| + | //! \param pPoint2 is a pointer to the second point. | ||
| + | //! \param pPoint3 is a pointer to the third point. | ||
| + | //! | ||
| + | //! This function draws a triangle specified by three points. | ||
| + | //! | ||
| + | //! \return None. | ||
| + | // | ||
| + | // | ||
| + | void | ||
| + | GrTriangleDraw(const tContext *pContext, const tPoint *pPoint1, | ||
| + | const tPoint *pPoint2, const tPoint *pPoint3) | ||
| + | { | ||
| + | tPoint pPoints[3]; | ||
| + | |||
| + | pPoints[0] = *pPoint1; | ||
| + | pPoints[1] = *pPoint2; | ||
| + | pPoints[2] = *pPoint3; | ||
| + | |||
| + | GrPolyDraw(pContext, | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // | ||
| + | //! Draws a filled triangle. | ||
| + | //! | ||
| + | //! \param pContext is a pointer to the drawing context to use. | ||
| + | //! \param pPoint1 is a pointer to the first point. | ||
| + | //! \param pPoint2 is a pointer to the second point. | ||
| + | //! \param pPoint3 is a pointer to the third point. | ||
| + | //! | ||
| + | //! This function fills a triangle specified by three points. | ||
| + | //! | ||
| + | //! \return None. | ||
| + | // | ||
| + | // | ||
| + | void | ||
| + | GrTriangleFill(const tContext *pContext, const tPoint *pPoint1, | ||
| + | const tPoint *pPoint2, const tPoint *pPoint3) | ||
| + | { | ||
| + | tPoint pPoints[3]; | ||
| + | |||
| + | pPoints[0] = *pPoint1; | ||
| + | pPoints[1] = *pPoint2; | ||
| + | pPoints[2] = *pPoint3; | ||
| + | |||
| + | GrPolyFill(pContext, | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // | ||
| + | //! Draws a quad. | ||
| + | //! | ||
| + | //! \param pContext is a pointer to the drawing context to use. | ||
| + | //! \param pPoint1 is a pointer to the first point. | ||
| + | //! \param pPoint2 is a pointer to the second point. | ||
| + | //! \param pPoint3 is a pointer to the third point. | ||
| + | //! \param pPoint4 is a pointer to the fourth point. | ||
| + | //! | ||
| + | //! This function draws a quad specified by four points. | ||
| + | //! | ||
| + | //! \return None. | ||
| + | // | ||
| + | // | ||
| + | void | ||
| + | GrQuadDraw(const tContext *pContext, const tPoint *pPoint1, | ||
| + | const tPoint *pPoint2, const tPoint *pPoint3, | ||
| + | const tPoint *pPoint4) | ||
| + | { | ||
| + | tPoint pPoints[4]; | ||
| + | |||
| + | pPoints[0] = *pPoint1; | ||
| + | pPoints[1] = *pPoint2; | ||
| + | pPoints[2] = *pPoint3; | ||
| + | pPoints[3] = *pPoint4; | ||
| + | |||
| + | GrPolyDraw(pContext, | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // | ||
| + | //! Draws a filled quad. | ||
| + | //! | ||
| + | //! \param pContext is a pointer to the drawing context to use. | ||
| + | //! \param pPoint1 is a pointer to the first point. | ||
| + | //! \param pPoint2 is a pointer to the second point. | ||
| + | //! \param pPoint3 is a pointer to the third point. | ||
| + | //! \param pPoint4 is a pointer to the fourth point. | ||
| + | //! | ||
| + | //! This function fills a quad specified by four points. | ||
| + | //! | ||
| + | //! The clipping of the polygon to the clipping rectangle is performed within | ||
| + | //! this routine; | ||
| + | //! | ||
| + | //! \return None. | ||
| + | // | ||
| + | // | ||
| + | void | ||
| + | GrQuadFill(const tContext *pContext, const tPoint *pPoint1, | ||
| + | const tPoint *pPoint2, const tPoint *pPoint3, | ||
| + | const tPoint *pPoint4) | ||
| + | { | ||
| + | tPoint pPoints[4]; | ||
| + | |||
| + | pPoints[0] = *pPoint1; | ||
| + | pPoints[1] = *pPoint2; | ||
| + | pPoints[2] = *pPoint3; | ||
| + | pPoints[3] = *pPoint4; | ||
| + | |||
| + | GrPolyFill(pContext, | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // | ||
| + | // Close the Doxygen group. | ||
| + | //! @} | ||
| + | // | ||
| + | // | ||
| + | </ | ||
| + | |||
| + | ===== grlib.h ===== | ||
| + | |||
| + | <code c> | ||
| + | // | ||
| + | // | ||
| + | //! This structure defines the point. | ||
| + | // | ||
| + | // | ||
| + | typedef struct | ||
| + | { | ||
| + | // | ||
| + | //! The X coordinate of the point. | ||
| + | // | ||
| + | short sX; | ||
| + | |||
| + | // | ||
| + | //! The Y coordinate of the point. | ||
| + | // | ||
| + | short sY; | ||
| + | } | ||
| + | tPoint; | ||
| + | |||
| + | // Add these also: | ||
| + | |||
| + | extern void GrPolyDraw(const tContext *pContext, const tPoint *pPoints, | ||
| + | | ||
| + | extern void GrPolyFill(const tContext *pContext, const tPoint *pPoints, | ||
| + | | ||
| + | extern void GrTriangleDraw(const tContext *pContext, const tPoint *pPoint1, | ||
| + | const tPoint *pPoint2, const tPoint *pPoint3); | ||
| + | extern void GrTriangleFill(const tContext *pContext, const tPoint *pPoint1, | ||
| + | const tPoint *pPoint2, const tPoint *pPoint3); | ||
| + | extern void GrQuadDraw(const tContext *pContext, const tPoint *pPoint1, | ||
| + | const tPoint *pPoint2, const tPoint *pPoint3, | ||
| + | const tPoint *pPoint4); | ||
| + | extern void GrQuadFill(const tContext *pContext, const tPoint *pPoint1, | ||
| + | const tPoint *pPoint2, const tPoint *pPoint3, | ||
| + | const tPoint *pPoint4); | ||
| + | |||
| + | </ | ||