//WholeBodyAnalysis.c #include "WholeBodyAnalysis.h" #include "annotate.h" #include "utils.h" #include "limits.h" // The code for this annotation is much easier to understand if you look at the diagram below // CP# means Control Point or Handle // Line# means line // // // CP0 Line0 CP1 // ************************* // * * // * Line2 Line1 * // * * // CP2 ********************************* CP3 // Line3 // // // Line4 // CP4 ********************************* CP5 // ** ** // * * * * // * *Line8 Line9* * // * * CP11 * * // * *********************** * // * CP6 * CP7 * // Line7 * * * Line5 // * * * // * * * // * * Line11 * // * * * // * * * // * Line6 * Line6 * // ********************************* // CP8 CP10 CP9 //************************************************************************************** // // Functions for WholeBodyAnalysis // //************************************************************************************* L_VOID WholeBodyAnalysis_AddHandle(HANNOBJECT hObject, ANNPOINT apt, pHANDLEDEF pHandleDef, L_BOOL bVisible) { L_UINT uFlags = ANNHANDLE_LOCATION | ANNHANDLE_CONTAINER_COORDINATES | ANNHANDLE_ID | ANNHANDLE_PEN_COLOR | ANNHANDLE_FILL_COLOR | ANNHANDLE_SHAPE | ANNHANDLE_VISIBLE; ANNHANDLE AnnHandle; AnnHandle.uStructSize = sizeof(ANNHANDLE); AnnHandle.nShape = pHandleDef->nShape; AnnHandle.crPen = RGB(0,0,0); AnnHandle.hCursor= NULL; AnnHandle.aptContainer = apt; AnnHandle.nID = pHandleDef->nID; AnnHandle.crFill = pHandleDef->crFill; AnnHandle.bVisible = bVisible; AnnHandle.uFlags = uFlags; L_AnnAddUserHandle(hObject, &AnnHandle); } #define WHOLEBOYDANALYSYS_NUMPOINTS 12 HANDLEDEF WholeBodyAnalysis_HandleDef[WHOLEBOYDANALYSYS_NUMPOINTS] = { HANDLE_ID_CP0, ANNHANDLE_SHAPE_CIRCLE, RGB(0,0,0), HANDLE_ID_CP1, ANNHANDLE_SHAPE_CIRCLE, RGB(128,128,128), HANDLE_ID_CP2, ANNHANDLE_SHAPE_CIRCLE, RGB(255,0,0), HANDLE_ID_CP3, ANNHANDLE_SHAPE_CIRCLE, RGB(0,255,0), HANDLE_ID_CP4, ANNHANDLE_SHAPE_CIRCLE, RGB(0,0,255), HANDLE_ID_CP5, ANNHANDLE_SHAPE_CIRCLE, RGB(255,255,0), HANDLE_ID_CP6, ANNHANDLE_SHAPE_CIRCLE, RGB(255,0,255), HANDLE_ID_CP7, ANNHANDLE_SHAPE_CIRCLE, RGB(0,255,255), HANDLE_ID_CP8, ANNHANDLE_SHAPE_CIRCLE, RGB(0,0,0), HANDLE_ID_CP9, ANNHANDLE_SHAPE_CIRCLE, RGB(128,128,128), HANDLE_ID_CP10,ANNHANDLE_SHAPE_CIRCLE, RGB(255,0,0), HANDLE_ID_CP11,ANNHANDLE_SHAPE_SQUARE, RGB(0,255,0), }; // Swaps if necessary, to make aptLine[0] to the left of aptLine[1] L_VOID WholeBodyAnalysis_SwapLeft(ANNPOINT aptLine[]) { if (aptLine[0].x > aptLine[1].x) SwapAnnPoints(aptLine + 0, aptLine + 1); } // Swaps if necessary, to make aptLine[0] above aptLine[1] L_VOID WholeBodyAnalysis_SwapTop(ANNPOINT aptLine[]) { if (aptLine[0].y > aptLine[1].y) SwapAnnPoints(aptLine + 0, aptLine + 1); } // WholeBodyAnalysis_AddUserHandles L_VOID WholeBodyAnalysis_AddUserHandles(LPCHILDDATA pData, HANNOBJECT hLine0) { ANNPOINT aptLine[2]; L_INT32 nCount; HANNOBJECT hLine; ANNPOINT apt; AnnGetNeighborObjects( hLine0, pData->AnnObjectNeighbors, &nCount); AnnSortNeighborObjects(hLine0, pData->AnnObjectNeighbors, nCount); annDebugDumpNeighborObjects( pData->AnnObjectNeighbors, nCount); L_AnnBringToFront(pData->AnnObjectNeighbors[0]); L_AnnBringToFront(pData->AnnObjectNeighbors[2]); L_AnnBringToFront(pData->AnnObjectNeighbors[4]); L_AnnBringToFront(pData->AnnObjectNeighbors[6]); L_AnnBringToFront(pData->AnnObjectNeighbors[10]); // Line0 hLine = pData->AnnObjectNeighbors[0]; L_AnnGetPoints(hLine, aptLine); WholeBodyAnalysis_SwapLeft(aptLine); WholeBodyAnalysis_AddHandle(hLine, aptLine[0], WholeBodyAnalysis_HandleDef + 0, TRUE); WholeBodyAnalysis_AddHandle(hLine, aptLine[1], WholeBodyAnalysis_HandleDef + 1, TRUE); // Line2 hLine = pData->AnnObjectNeighbors[2]; L_AnnGetPoints(pData->AnnObjectNeighbors[2], aptLine); WholeBodyAnalysis_SwapLeft(aptLine); WholeBodyAnalysis_AddHandle(hLine, aptLine[0], WholeBodyAnalysis_HandleDef + 2, TRUE); WholeBodyAnalysis_AddHandle(hLine, aptLine[1], WholeBodyAnalysis_HandleDef + 3, TRUE); // Line4 hLine = pData->AnnObjectNeighbors[4]; L_AnnGetPoints(pData->AnnObjectNeighbors[4], aptLine); WholeBodyAnalysis_SwapLeft(aptLine); WholeBodyAnalysis_AddHandle(hLine, aptLine[0], WholeBodyAnalysis_HandleDef + 4, TRUE); WholeBodyAnalysis_AddHandle(hLine, aptLine[1], WholeBodyAnalysis_HandleDef + 5, TRUE); // Line6 hLine = pData->AnnObjectNeighbors[6]; L_AnnGetPoints(pData->AnnObjectNeighbors[6], aptLine); WholeBodyAnalysis_SwapLeft(aptLine); WholeBodyAnalysis_AddHandle(hLine, aptLine[0], WholeBodyAnalysis_HandleDef + 8, TRUE); WholeBodyAnalysis_AddHandle(hLine, aptLine[1], WholeBodyAnalysis_HandleDef + 9, TRUE); // Line10 hLine = pData->AnnObjectNeighbors[10]; L_AnnGetPoints(pData->AnnObjectNeighbors[10], aptLine); WholeBodyAnalysis_SwapLeft(aptLine); WholeBodyAnalysis_AddHandle(hLine, aptLine[0], WholeBodyAnalysis_HandleDef + 6, TRUE); WholeBodyAnalysis_AddHandle(hLine, aptLine[1], WholeBodyAnalysis_HandleDef + 7, TRUE); apt.x = (aptLine[0].x + aptLine[1].x) / 2; apt.y = (aptLine[0].y + aptLine[1].y) / 2; WholeBodyAnalysis_AddHandle(hLine, apt, WholeBodyAnalysis_HandleDef + 11, FALSE); // hidden handle // Line11--handle corresponding to bottom point goes on line6 hLine = pData->AnnObjectNeighbors[6]; L_AnnGetPoints(pData->AnnObjectNeighbors[11], aptLine); WholeBodyAnalysis_SwapTop(aptLine); WholeBodyAnalysis_AddHandle(hLine, aptLine[1], WholeBodyAnalysis_HandleDef + 10, TRUE); } #define MIN_DIST (10) L_VOID WholeBodyAnalysis_RestrictPoint(LPCHILDDATA pData) { RECT rcClip; ANNRECT arcContainer; POINT pt0, pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8, pt9, pt10; // client coordinates of handles CP0 ... CP3 L_AnnGetRect(pData->hContainer, &arcContainer, NULL); L_AnnConvert(pData->hContainer, (LPPOINT)&rcClip, (pANNPOINT)&arcContainer, 2, ANNCONVERT_TO_CLIENT); // Get location of all handles in client coordinates GetHandleInfo(pData->AnnObjectNeighbors[0], HANDLE_ID_CP0, &pt0, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[0], HANDLE_ID_CP1, &pt1, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[2], HANDLE_ID_CP2, &pt2, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[2], HANDLE_ID_CP3, &pt3, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[4], HANDLE_ID_CP4, &pt4, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[4], HANDLE_ID_CP5, &pt5, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[10], HANDLE_ID_CP6, &pt6, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[10], HANDLE_ID_CP7, &pt7, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[6], HANDLE_ID_CP8, &pt8, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[6], HANDLE_ID_CP9, &pt9, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[6], HANDLE_ID_CP10, &pt10, NULL, NULL); switch(pData->nUserHandleID) { case HANDLE_ID_CP0: rcClip.right = min(pt1.x, pt3.x) - MIN_DIST; rcClip.bottom = pt3.y - MIN_DIST; break; case HANDLE_ID_CP1: rcClip.left = max(pt0.x, pt2.x) + MIN_DIST; rcClip.bottom = pt3.y - MIN_DIST; break; case HANDLE_ID_CP2: rcClip.right = min(pt1.x, pt3.x) - MIN_DIST; rcClip.top = pt0.y + MIN_DIST; rcClip.bottom = pt4.y - MIN_DIST; break; case HANDLE_ID_CP3: rcClip.left = max(pt0.x, pt2.x) + MIN_DIST; rcClip.top = pt0.y + MIN_DIST; rcClip.bottom = pt4.y - MIN_DIST; break; case HANDLE_ID_CP4: rcClip.top = pt2.y + MIN_DIST; rcClip.bottom = pt6.y - MIN_DIST; rcClip.right = pt6.x - MIN_DIST; break; case HANDLE_ID_CP5: rcClip.top = pt2.y + MIN_DIST; rcClip.bottom = pt7.y - MIN_DIST; rcClip.left = pt7.x + MIN_DIST; break; case HANDLE_ID_CP6: rcClip.top = pt4.y + MIN_DIST; rcClip.bottom = pt8.y - MIN_DIST; rcClip.left = max(pt4.x, pt8.x) + MIN_DIST; rcClip.right = pt7.x - MIN_DIST; break; case HANDLE_ID_CP7: rcClip.top = pt4.y + MIN_DIST; rcClip.bottom = pt8.y - MIN_DIST; rcClip.left = pt6.x + MIN_DIST; rcClip.right = min(pt5.x, pt9.x) - MIN_DIST; break; case HANDLE_ID_CP8: rcClip.top = pt6.y + MIN_DIST; rcClip.right = min(pt6.x, pt10.x) - MIN_DIST; break; case HANDLE_ID_CP9: rcClip.top = pt6.y + MIN_DIST; rcClip.left = max(pt7.x, pt10.x) + MIN_DIST; break; case HANDLE_ID_CP10: rcClip.top = pt6.y + MIN_DIST; rcClip.left = pt8.x + MIN_DIST; rcClip.right = pt9.x - MIN_DIST; break; } L_AnnRestrictCursor(pData->hContainer, &rcClip, NULL, NULL, FALSE); } // Used to handle movement of three lines when moving a vertex of a line that always stays horizontal // We are moving one of the handles {L,M} // ptMove--client coordinates of handle we are moving // nLine0, nLine1, nLineHorizontal are indices into pData->AnnObjectNeighbors, which is the array of handles of lines // nHandleID0 is the handleID of the handle we are moving on nLineHorizontal // nHandleID1 is the handleID of the other handle of nLineHorizontal // bMovingLeft -- TRUE if moving the handle L, FALSE if moving handle R // bUpdateHorizontal -- TRUE to update the horizontal line, FALSE to leave it alone // // L nLineHorizontal R // **************************** // * * // nLine0 * * nLine1 // * * // * * L_VOID WholeBodyAnalysis_Handle_LButtonDown_ThreeLines( LPCHILDDATA pData, POINT ptMove, L_INT nLine0, L_INT nLineHorizontal, L_INT nLine1, L_INT nHandleID1, L_BOOL bMovingLeft, L_BOOL bUpdateHorizontal ) { POINT pt1; pData->ObjectWholeBodyAnalysis.bMovingLeft = bMovingLeft; // Line Horizontal if (bUpdateHorizontal) L_AnnDefine(pData->AnnObjectNeighbors[nLineHorizontal], &ptMove, ANNDEFINE_BEGINMOVEPOINT); // Line0 L_AnnDefine(pData->AnnObjectNeighbors[nLine0], &ptMove, ANNDEFINE_BEGINMOVEPOINT); // Line1 GetHandleInfo(pData->AnnObjectNeighbors[nLineHorizontal], nHandleID1, &pt1, NULL, NULL); pData->ObjectWholeBodyAnalysis.pt1 = pt1; pt1.y = ptMove.y; L_AnnDefine(pData->AnnObjectNeighbors[nLine1], &pData->ObjectWholeBodyAnalysis.pt1, ANNDEFINE_BEGINMOVEPOINT); } // See decscription of WholeBodyAnalysis_Handle_LButtonDownThreeLines L_VOID WholeBodyAnalysis_Handle_MouseMove_ThreeLines( LPCHILDDATA pData, POINT ptMove, L_INT nLine0, L_INT nLineHorizontal, L_INT nLine1, L_INT nHandleID1, L_BOOL bMovingLeft, L_BOOL bUpdateHorizontal ) { POINT pt1; //ANNDEFINE_UPDATE not supported for ANNDEFINE_MOVEPOINT--use ANNDEFINE_APPEND pData->ObjectWholeBodyAnalysis.bMovingLeft = bMovingLeft; // Line Horizontal if (bUpdateHorizontal) { pData->ObjectWholeBodyAnalysis.bLineAdjust = TRUE; L_AnnDefine(pData->AnnObjectNeighbors[nLineHorizontal], &ptMove, ANNDEFINE_APPEND); } // Line0 pData->ObjectWholeBodyAnalysis.bLineAdjust = FALSE; L_AnnDefine(pData->AnnObjectNeighbors[nLine0], &ptMove, ANNDEFINE_APPEND); // Line1 pData->ObjectWholeBodyAnalysis.bLineAdjust = FALSE; pt1 = pData->ObjectWholeBodyAnalysis.pt1; pt1.y = ptMove.y; L_AnnDefine(pData->AnnObjectNeighbors[nLine1], &pt1, ANNDEFINE_APPEND); } // See description of WholeBodyAnalysis_Handle_LButtonDownThreeLines L_VOID WholeBodyAnalysis_Handle_LButtonUp_ThreeLines( LPCHILDDATA pData, POINT ptMove, L_INT nLine0, L_INT nLineHorizontal, L_INT nLine1, L_INT nHandleID1, L_BOOL bMovingLeft, L_BOOL bUpdateHorizontal ) { POINT pt1; pData->ObjectWholeBodyAnalysis.bMovingLeft = bMovingLeft; // Line Horizontal pt1 = pData->ObjectWholeBodyAnalysis.pt1; if (bUpdateHorizontal) { L_AnnDefine(pData->AnnObjectNeighbors[nLineHorizontal], &ptMove, ANNDEFINE_END); // Change line horizontal to new location, and move handle nHandleID1 L_AnnDefine(pData->AnnObjectNeighbors[nLineHorizontal], &pt1, ANNDEFINE_BEGINMOVEPOINT); pt1 = pData->ObjectWholeBodyAnalysis.pt1; pt1.y = ptMove.y; L_AnnDefine(pData->AnnObjectNeighbors[nLineHorizontal], &pt1, ANNDEFINE_END); MoveHandle(pData->hObjectChange, nHandleID1, pt1); } // Line0 L_AnnDefine(pData->AnnObjectNeighbors[nLine0], &ptMove, ANNDEFINE_END); // Line1 pt1 = pData->ObjectWholeBodyAnalysis.pt1; pt1.y = ptMove.y; L_AnnDefine(pData->AnnObjectNeighbors[nLine1], &pt1, ANNDEFINE_END); } // L_VOID WholeBodyAnalysis_Handle_LButtonDown(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { L_INT nCount; AnnGetNeighborObjects( pData->hObjectChange, pData->AnnObjectNeighbors, &nCount); AnnSortNeighborObjects(pData->hObjectChange, pData->AnnObjectNeighbors, nCount); WholeBodyAnalysis_RestrictPoint(pData); pData->ObjectWholeBodyAnalysis.bLineAdjust = FALSE; switch (pData->nUserHandleID) { case HANDLE_ID_CP0: WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,3,0,1, HANDLE_ID_CP1, TRUE, TRUE); break; case HANDLE_ID_CP1: WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,1,0,3, HANDLE_ID_CP0, FALSE, TRUE); break; case HANDLE_ID_CP2: WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,3,2,1, HANDLE_ID_CP3, FALSE, TRUE); break; case HANDLE_ID_CP3: WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,1,2,3, HANDLE_ID_CP2, TRUE, TRUE); break; case HANDLE_ID_CP4: WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,8,4,9, HANDLE_ID_CP5, TRUE, TRUE); WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,7,4,5, HANDLE_ID_CP5, TRUE, FALSE); break; case HANDLE_ID_CP5: WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,9,4,8, HANDLE_ID_CP4, FALSE, TRUE); WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,5,4,7, HANDLE_ID_CP4, FALSE, FALSE); break; case HANDLE_ID_CP8: WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,7,6,5, HANDLE_ID_CP9, FALSE, TRUE); GetHandleInfo(pData->AnnObjectNeighbors[6], HANDLE_ID_CP10, &pData->ObjectWholeBodyAnalysis.pt10, NULL, NULL); L_AnnDefine(pData->AnnObjectNeighbors[11], &pData->ObjectWholeBodyAnalysis.pt10, ANNDEFINE_BEGINMOVEPOINT); break; case HANDLE_ID_CP9: WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,5,6,7, HANDLE_ID_CP8, TRUE, TRUE); GetHandleInfo(pData->AnnObjectNeighbors[6], HANDLE_ID_CP10, &pData->ObjectWholeBodyAnalysis.pt10, NULL, NULL); L_AnnDefine(pData->AnnObjectNeighbors[11], &pData->ObjectWholeBodyAnalysis.pt10, ANNDEFINE_BEGINMOVEPOINT); break; case HANDLE_ID_CP6: WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,8,10,9, HANDLE_ID_CP7, FALSE, TRUE); GetHandleInfo(pData->AnnObjectNeighbors[10], HANDLE_ID_CP11, &pData->ObjectWholeBodyAnalysis.pt11, NULL, NULL); L_AnnDefine(pData->AnnObjectNeighbors[11], &pData->ObjectWholeBodyAnalysis.pt11, ANNDEFINE_BEGINMOVEPOINT); break; case HANDLE_ID_CP7: WholeBodyAnalysis_Handle_LButtonDown_ThreeLines(pData,pMousePos->pt,9,10,8, HANDLE_ID_CP6, TRUE, TRUE); GetHandleInfo(pData->AnnObjectNeighbors[10], HANDLE_ID_CP11, &pData->ObjectWholeBodyAnalysis.pt11, NULL, NULL); L_AnnDefine(pData->AnnObjectNeighbors[11], &pData->ObjectWholeBodyAnalysis.pt11, ANNDEFINE_BEGINMOVEPOINT); break; case HANDLE_ID_CP10: L_AnnDefine(pData->AnnObjectNeighbors[11], &pMousePos->pt, ANNDEFINE_BEGINMOVEPOINT); L_AnnDefine(pData->AnnObjectNeighbors[6], &pMousePos->pt, ANNDEFINE_BEGINMOVE); GetHandleInfo(pData->AnnObjectNeighbors[6], HANDLE_ID_CP8, &pData->ObjectWholeBodyAnalysis.pt8, NULL, NULL); GetHandleInfo(pData->AnnObjectNeighbors[6], HANDLE_ID_CP9, &pData->ObjectWholeBodyAnalysis.pt9, NULL, NULL); L_AnnDefine(pData->AnnObjectNeighbors[7], &pData->ObjectWholeBodyAnalysis.pt8, ANNDEFINE_BEGINMOVEPOINT); L_AnnDefine(pData->AnnObjectNeighbors[5], &pData->ObjectWholeBodyAnalysis.pt9, ANNDEFINE_BEGINMOVEPOINT); break; } } L_VOID WholeBodyAnalysis_Handle_MouseMove(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { POINT pt; switch (pData->nUserHandleID) { case HANDLE_ID_CP0: WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,3,0,1, HANDLE_ID_CP1, TRUE, TRUE); break; case HANDLE_ID_CP1: WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,1,0,3, HANDLE_ID_CP0, FALSE, TRUE); break; case HANDLE_ID_CP2: WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,3,2,1, HANDLE_ID_CP3, FALSE, TRUE); break; case HANDLE_ID_CP3: WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,1,2,3, HANDLE_ID_CP2, TRUE, TRUE); break; case HANDLE_ID_CP4: WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,8,4,9, HANDLE_ID_CP5, TRUE, TRUE); WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,7,4,5, HANDLE_ID_CP5, TRUE, FALSE); break; case HANDLE_ID_CP5: WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,9,4,8, HANDLE_ID_CP4, FALSE, TRUE); WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,5,4,7, HANDLE_ID_CP4, FALSE, FALSE); break; case HANDLE_ID_CP8: pt = pData->ObjectWholeBodyAnalysis.pt10; pt.y = pMousePos->pt.y; L_AnnDefine(pData->AnnObjectNeighbors[11], &pt, ANNDEFINE_APPEND); WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,7,6,5, HANDLE_ID_CP9, FALSE, TRUE); break; case HANDLE_ID_CP9: pt = pData->ObjectWholeBodyAnalysis.pt10; pt.y = pMousePos->pt.y; L_AnnDefine(pData->AnnObjectNeighbors[11], &pt, ANNDEFINE_APPEND); WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,5,6,7, HANDLE_ID_CP8, TRUE, TRUE); break; case HANDLE_ID_CP6: WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,8,10,9, HANDLE_ID_CP7, FALSE, TRUE); pt.x = pData->ObjectWholeBodyAnalysis.pt11.x + (pMousePos->pt.x - pData->ptStart.x) / 2; pt.y = pMousePos->pt.y; L_AnnDefine(pData->AnnObjectNeighbors[11], &pt, ANNDEFINE_APPEND); break; case HANDLE_ID_CP7: WholeBodyAnalysis_Handle_MouseMove_ThreeLines(pData,pMousePos->pt,9,10,8, HANDLE_ID_CP6, TRUE, TRUE); pt.x = pData->ObjectWholeBodyAnalysis.pt11.x + (pMousePos->pt.x - pData->ptStart.x) / 2; pt.y = pMousePos->pt.y; L_AnnDefine(pData->AnnObjectNeighbors[11], &pt, ANNDEFINE_APPEND); break; case HANDLE_ID_CP10: L_AnnDefine(pData->AnnObjectNeighbors[11], &pMousePos->pt, ANNDEFINE_APPEND); pt = pMousePos->pt; pt.x = pData->ptStart.x; L_AnnDefine(pData->AnnObjectNeighbors[6], &pt, ANNDEFINE_APPEND); pt = pData->ObjectWholeBodyAnalysis.pt8; pt.y += (pMousePos->pt.y - pData->ptStart.y); L_AnnDefine(pData->AnnObjectNeighbors[7], &pt, ANNDEFINE_APPEND); pt = pData->ObjectWholeBodyAnalysis.pt9; pt.y += (pMousePos->pt.y - pData->ptStart.y); L_AnnDefine(pData->AnnObjectNeighbors[5], &pt, ANNDEFINE_APPEND); break; } pMousePos->fUpdatePos = FALSE; } L_VOID WholeBodyAnalysis_Handle_LButtonUp(LPCHILDDATA pData, pANNMOUSEPOS pMousePos) { POINT pt; pData->ObjectWholeBodyAnalysis.bLineAdjust = FALSE; switch (pData->nUserHandleID) { case HANDLE_ID_CP0: WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,3,0,1, HANDLE_ID_CP1, TRUE, TRUE); break; case HANDLE_ID_CP1: WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,1,0,3, HANDLE_ID_CP0, FALSE, TRUE); break; case HANDLE_ID_CP2: WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,3,2,1, HANDLE_ID_CP3, FALSE, TRUE); break; case HANDLE_ID_CP3: WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,1,2,3, HANDLE_ID_CP2, TRUE, TRUE); break; case HANDLE_ID_CP4: WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,8,4,9, HANDLE_ID_CP5, TRUE, TRUE); WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,7,4,5, HANDLE_ID_CP5, TRUE, FALSE); break; case HANDLE_ID_CP5: WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,9,4,8, HANDLE_ID_CP4, FALSE, TRUE); WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,5,4,7, HANDLE_ID_CP4, FALSE, FALSE); break; case HANDLE_ID_CP8: pt = pData->ObjectWholeBodyAnalysis.pt10; pt.y = pMousePos->pt.y; L_AnnDefine(pData->AnnObjectNeighbors[11], &pt, ANNDEFINE_END); MoveHandle(pData->AnnObjectNeighbors[6], HANDLE_ID_CP10, pt); WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,7,6,5, HANDLE_ID_CP9, FALSE, TRUE); break; case HANDLE_ID_CP9: pt = pData->ObjectWholeBodyAnalysis.pt10; pt.y = pMousePos->pt.y; L_AnnDefine(pData->AnnObjectNeighbors[11], &pt, ANNDEFINE_END); MoveHandle(pData->AnnObjectNeighbors[6], HANDLE_ID_CP10, pt); WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,5,6,7, HANDLE_ID_CP8, TRUE, TRUE); break; case HANDLE_ID_CP6: WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,8,10,9, HANDLE_ID_CP7, FALSE, TRUE); pt.x = pData->ObjectWholeBodyAnalysis.pt11.x + (pMousePos->pt.x - pData->ptStart.x) / 2; pt.y = pMousePos->pt.y; L_AnnDefine(pData->AnnObjectNeighbors[11], &pt, ANNDEFINE_END); MoveHandle(pData->AnnObjectNeighbors[10], HANDLE_ID_CP11, pt); break; case HANDLE_ID_CP7: WholeBodyAnalysis_Handle_LButtonUp_ThreeLines(pData,pMousePos->pt,9,10,8, HANDLE_ID_CP6, TRUE, TRUE); pt.x = pData->ObjectWholeBodyAnalysis.pt11.x + (pMousePos->pt.x - pData->ptStart.x) / 2; pt.y = pMousePos->pt.y; L_AnnDefine(pData->AnnObjectNeighbors[11], &pt, ANNDEFINE_END); MoveHandle(pData->AnnObjectNeighbors[10], HANDLE_ID_CP11, pt); break; case HANDLE_ID_CP10: L_AnnDefine(pData->AnnObjectNeighbors[11], &pMousePos->pt, ANNDEFINE_END); pt = pMousePos->pt; pt.x = pData->ptStart.x; L_AnnDefine(pData->AnnObjectNeighbors[6], &pt, ANNDEFINE_END); pt = pData->ObjectWholeBodyAnalysis.pt8; pt.y += (pMousePos->pt.y - pData->ptStart.y); L_AnnDefine(pData->AnnObjectNeighbors[7], &pt, ANNDEFINE_END); pt = pData->ObjectWholeBodyAnalysis.pt9; pt.y += (pMousePos->pt.y - pData->ptStart.y); L_AnnDefine(pData->AnnObjectNeighbors[5], &pt, ANNDEFINE_END); break; } MoveHandle(pData->hObjectChange, pData->nUserHandleID, pMousePos->pt); } //*************** WholeBodyAnalysis Create functions L_VOID WholeBodyAnalysis_LButtonDown(HWND hWnd, LPCHILDDATA pData) { L_AnnAddUndoNode(pData->hAutomation); L_AnnCreateItem(pData->hContainer, ANNOBJECT_RECT, TRUE, &pData->hRect); L_AnnDefine(pData->hRect, &pData->ptStart, ANNDEFINE_BEGINSET); pData->fCapture = TRUE; L_AnnRestrictCursor(pData->hContainer, NULL, NULL, &pData->rcOldClip,TRUE); } L_VOID WholeBodyAnalysis_MouseMove(LPCHILDDATA pData) { L_AnnDefine(pData->hRect, &pData->ptMove, ANNDEFINE_UPDATE); } // I need to create 11 lines to define this object // To simplify this, assume that the object fills a unit box (1x1 units) // I define the object using these unit coordinates, then stretch the unit box into the bounding box defined by parcBounds HANNOBJECT WholeBodyAnalysis_CreateLine(HANNOBJECT hContainer, L_INT uTool, L_INT nID, pANNRECT parcBounds, L_DOUBLE dLeft, L_DOUBLE dTop, L_DOUBLE dRight, L_DOUBLE dBottom) { ANNPOINT aptLine[2]; HANNOBJECT hLine; L_DOUBLE dWidth, dHeight, dStartX, dStartY; if (!parcBounds) return NULL; L_AnnCreateItem(hContainer, ANNOBJECT_LINE, FALSE, &hLine); dStartX = parcBounds->left; dStartY = parcBounds->top; dWidth = parcBounds->right - parcBounds->left; dHeight = parcBounds->bottom - parcBounds->top; aptLine[0].x = dStartX + dWidth *dLeft;; aptLine[0].y = dStartY + dHeight*dTop; aptLine[1].x = dStartX + dWidth *dRight; aptLine[1].y = dStartY + dHeight*dBottom; L_AnnSetPoints(hLine, aptLine, 2); AnnSetID(hLine, uTool, nID); L_AnnSetVisible(hLine, TRUE, 0, NULL); HideDefaultHandles(hLine); L_AnnSetSelected(hLine, TRUE, 0); return hLine; } L_VOID WholeBodyAnalysis_LButtonUp(LPCHILDDATA pData, L_UINT uTool) { HANNOBJECT hLine0; ANNRECT arcRect; L_DOUBLE dx = 0.25; L_DOUBLE dy = 0.125; // Finish creating the rectangle L_AnnDefine(pData->hRect, &pData->ptEnd, ANNDEFINE_END); L_AnnGetRect(pData->hRect, &arcRect, NULL); // Delete the rectangle and create a polygon L_AnnRemove(pData->hRect); L_AnnDestroy(pData->hRect, 0); // Create the object by defining 11 lines // See diagram for full body analysis /* line 0 */ hLine0 = WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS, 0, &arcRect, 0, 0, 1, 0); /* line 1 */ WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS, 1, &arcRect, 1, 0, 1, 2*dy); /* line 2 */ WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS, 2, &arcRect, 1, 2*dy, 0, 2*dy); /* line 3 */ WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS, 3, &arcRect, 0, 2*dy, 0, 0); /* line 4 */ WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS, 4, &arcRect, 0, 3*dy, 1, 3*dy); /* line 5 */ WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS, 5, &arcRect, 1, 3*dy, 1, 1); /* line 6 */ WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS, 6, &arcRect, 1, 1, 0, 1); /* line 7 */ WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS, 7, &arcRect, 0, 1, 0, 3*dy); /* line 8 */ WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS, 8, &arcRect, dx, 5*dy, 0, 3*dy); /* line 9 */ WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS, 9, &arcRect, 1, 3*dy, 3*dx, 5*dy); /* line 10*/ WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS,10, &arcRect, 3*dx, 5*dy, dx, 5*dy); /* line 11*/ WholeBodyAnalysis_CreateLine(pData->hContainer, ANNTOOL_WHOLE_BODY_ANALYSIS,11, &arcRect, 2*dx, 5*dy, 2*dx, 1); // set the default settings from the automation object, and group the objects L_AnnSetAutoDefaults(pData->hAutomation, pData->hContainer, ANNFLAG_SELECTED|ANNFLAG_RECURSE); // Must group before adding user handles--otherwise call to GetNeighborObjects fails L_AnnGroup(pData->hContainer, ANNFLAG_SELECTED|ANNFLAG_RECURSE, NULL); WholeBodyAnalysis_AddUserHandles(pData, hLine0); } // *************** WholeBodyAnalysis Miscellaneous functions L_VOID WholeBodyAnalysis_Hilight(LPCHILDDATA pData, pANNHILIGHT pAnnHilight) { if (pData->ObjectWholeBodyAnalysis.bLineAdjust) { if (pData->ObjectWholeBodyAnalysis.bMovingLeft) pAnnHilight->ppts[1].y = pAnnHilight->ppts[0].y; else pAnnHilight->ppts[0].y = pAnnHilight->ppts[1].y; } }