// $Id: doccoord.cpp 1282 2006-06-09 09:46:49Z alex $ /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE ================================XARAHEADERSTART=========================== Xara LX, a vector drawing and manipulation program. Copyright (C) 1993-2006 Xara Group Ltd. Copyright on certain contributions may be held in joint with their respective authors. See AUTHORS file for details. LICENSE TO USE AND MODIFY SOFTWARE ---------------------------------- This file is part of Xara LX. Xara LX is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. Xara LX and its component source files are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Xara LX (see the file GPL in the root directory of the distribution); if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ADDITIONAL RIGHTS ----------------- Conditional upon your continuing compliance with the GNU General Public License described above, Xara Group Ltd grants to you certain additional rights. The additional rights are to use, modify, and distribute the software together with the wxWidgets library, the wxXtra library, and the "CDraw" library and any other such library that any version of Xara LX relased by Xara Group Ltd requires in order to compile and execute, including the static linking of that library to XaraLX. In the case of the "CDraw" library, you may satisfy obligation under the GNU General Public License to provide source code by providing a binary copy of the library concerned and a copy of the license accompanying it. Nothing in this section restricts any of the rights you have under the GNU General Public License. SCOPE OF LICENSE ---------------- This license applies to this program (XaraLX) and its constituent source files only, and does not necessarily apply to other Xara products which may in part share the same code base, and are subject to their own licensing terms. This license does not apply to files in the wxXtra directory, which are built into a separate library, and are subject to the wxWindows license contained within that directory in the file "WXXTRA-LICENSE". This license does not apply to the binary libraries (if any) within the "libs" directory, which are subject to a separate license contained within that directory in the file "LIBS-LICENSE". ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS ---------------------------------------------- Subject to the terms of the GNU Public License (see above), you are free to do whatever you like with your modifications. However, you may (at your option) wish contribute them to Xara's source tree. You can find details of how to do this at: http://www.xaraxtreme.org/developers/ Prior to contributing your modifications, you will need to complete our contributor agreement. This can be found at: http://www.xaraxtreme.org/developers/contribute/ Please note that Xara will not accept modifications which modify any of the text between the start and end of this header (marked XARAHEADERSTART and XARAHEADEREND). MARKS ----- Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara designs are registered or unregistered trademarks, design-marks, and/or service marks of Xara Group Ltd. All rights in these marks are reserved. Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. http://www.xara.com/ =================================XARAHEADEREND============================ */ #include "camtypes.h" //#include "doccoord.h" - in camtypes.h [AUTOMATICALLY REMOVED] #if !defined(EXCLUDE_FROM_XARLIB) #include "usercord.h" //#include "node.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "paper.h" //#include "xmatrix.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "spread.h" - in camtypes.h [AUTOMATICALLY REMOVED] #include "chapter.h" //#include "oilcoord.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "view.h" - in camtypes.h [AUTOMATICALLY REMOVED] //#include "document.h" - in camtypes.h [AUTOMATICALLY REMOVED] /******************************************************************************************** > Matrix ComposeDocToOilMat( DocCoord& ChapterPos, XLONG& ChapterLogHiY, FIXED16& ViewScale, WorkCoord& Scroll, ) Author: Will_Cowling (Xara Group Ltd) Created: 5/8/93 Inputs: Chapter physical position Accumulated depth of previous chapters View scale factor (always 1:1 aspect ratio) Individual millipoint to pixel scale factors Scroll offsets Final device-dependant mapping matrix Outputs: None. Returns: Document to Oil matrix for a specific chapter. Purpose: Creates a Document to Oil matrix for a specific chapter. Errors: None. ********************************************************************************************/ /* Technical notes: Assumes that the top corner of logical space is at 0,0 and y gets more negative downwards Assumes that the top corner of workarea space is at 0,0... Assumes that scroll.x is positive and that scroll.y is negative. Assumes that Document space can never be rotated with respect to OS space! ********************************************************************************************/ Matrix ComposeDocToOilMat( const DocCoord& ChapterPos, // Top left coord of chapter const XLONG& ChapterDepth, // Accumulated height of previous chaps const FIXED16& ViewScale, // User viewing scale const WorkCoord& ScrollOffset // Scroll offsets ) { // Scale ChapterDepth into device units so that it can be combined with the scroll offset // BEFORE we build the scroll translation matrix. In this way we avoid storing 64-bit // translation values in our final matrix... // // If we COULD store 64-bit E and F values temporarilly during this composition then // we would not need to perform this trick at all. This would have the knock-on advantage // that the OSMapping matrix supplied by the OIL layer could contain the scroll offsets! // // NOTE: This adjustment can be removed when testing the system! Matrix DocToOil; //********************************************************************** // Is it just me or is there gunna be a problem with this ? // If ChapterDepth is big (atfer all it is an XLONG) and ViewScale // is big too (Say we are zoomed to 1000%) won't this go VERY wrong ? // // - Will. Matrix Scroll( -ScrollOffset.x, -(ScrollOffset.y + (ChapterDepth * (ViewScale))) ); //********************************************************************** Matrix ScaleMat(ViewScale,ViewScale); Matrix Translate(-((Coord)ChapterPos)); // The following matrix compositions MUST be performed in this order. If you are tempted // to optimise this code MAKE SURE THAT THEY ARE STILL IN THIS ORDER WHEN YOU'VE FINISHED! // // Apply translation to get coordinates into logical column... DocToOil *= Translate; // Apply scale factors to convert from millipoint distances to pixel distances... DocToOil *= ScaleMat; // Apply scroll-offset translation to move origin to viewing position... DocToOil *= Scroll; return DocToOil; } /******************************************************************************************** > Matrix ComposeDocToWorkXMat(DocCoord ChapterPos, XLONG ChapterDepth, FIXED16 ViewScale ) Author: Mario_Shamtani (Xara Group Ltd) Created: 30/5/93 Inputs: Chapter physical position Accumulated depth of previous chapters View scale factor (always 1:1 aspect ratio) Individual millipoint to pixel scale factors Outputs: None. Returns: Document to WorkArea matrix for a specific chapter. Purpose: Creates a Document to WorkArea matrix for a specific chapter. Errors: None. ********************************************************************************************/ /* Technical notes: Assumes that the top corner of logical space is at 0,0 and y gets more negative downwards Assumes that the top corner of workarea space is at 0,0... Assumes that scroll.x is positive and that scroll.y is negative. ********************************************************************************************/ XMatrix ComposeDocToWorkXMat(const DocCoord ChapterPos, // Top left coord of chapter const XLONG ChapterDepth, // Accumulated height of previous chaps const FIXED16 ViewScale // User viewing scale ) { XMatrix ScaleMat(ViewScale,ViewScale); // Conversion of chapter position from DocCoords to WorkCoords // WorkCoord WrkChapPos(MakeXLong(ChapterPos.x), MakeXLong(ChapterPos.y)); WorkCoord WrkChapPos(MakeXLong(ChapterPos.x), MakeXLong(ChapterPos.y)+ChapterDepth); // DocToOS matrix is initialised as the Translate matrix: saving space and performance // by the exclusion of an extra multiplication. XMatrix DocToWork(-(WrkChapPos)); // The following matrix compositions MUST be performed in this order. If you are tempted // to optimise this code MAKE SURE THAT THEY ARE STILL IN THIS ORDER WHEN YOU'VE FINISHED! // // Apply scale factors to convert from millipoint distances to pixel distances... DocToWork *= ScaleMat; return DocToWork; } /******************************************************************************************** > WorkCoord DocCoord::ToWork(Document *pDocument, View *pView) Author: Mario_Shamtani (Xara Group Ltd) (with modifications by Phil (and Tim)) Created: 26/5/93 Inputs: The document we are converting within. The view we are converting within. Outputs: None. Returns: Returns a Workarea coordinate. Purpose: Converts a document coordinate to a work area coordnate - slowly! Note that if you are performing this conversion often and you want to do it fast then you should use the approriate "Compose" function to build a matrix which does the job and repeatedly apply that matrix. Errors: None. ********************************************************************************************/ /* Technical notes: ********************************************************************************************/ WorkCoord DocCoord::ToWork(Document *pDocument, View *pView) { WorkCoord WrkPoint(MakeXLong(this->x), MakeXLong(this->y)); DocCoord ChapterPos; // To hold the top-left of the found chapter XLONG ChapterDepth; // To hold the accumulated depth of the chapter XMatrix ConvertToWorkMat; // Transformation matrix // Find chapter and its log depth this->FindEnclosingChapter(pDocument, &ChapterPos, &ChapterDepth, pView); // This builds the 64-bit conversion matrix needed for Document To WorkArea // coordinate mappings. ConvertToWorkMat = ComposeDocToWorkXMat(ChapterPos, ChapterDepth, pView->GetViewScale()); // Apply the matrix to the DocCoord... ConvertToWorkMat.transform(&WrkPoint, 1); return (WrkPoint); } /******************************************************************************************** > WorkCoord DocCoord::ToWork( Spread *pSpread, const FIXED16 ViewScale) Author: Tim_Browse (Xara Group Ltd) Created: 15/12/93 Inputs: - Outputs: - Returns: - Purpose: Convert a document coordinate to a Work Coordinate, given the spread that the coordinate is on. Errors: - SeeAlso: - ********************************************************************************************/ WorkCoord DocCoord::ToWork( Spread *pSpread, View *pView) { WorkCoord WrkPoint(MakeXLong(this->x), MakeXLong(this->y)); DocCoord ChapterPos; // To hold the top-left of the found chapter XLONG ChapterDepth; // To hold the accumulated depth of the chapter XMatrix ConvertToWorkMat; // Transformation matrix Chapter *pChapter = (Chapter *) pSpread->FindParent(); ENSURE(pChapter->IsKindOf(CC_RUNTIME_CLASS(Chapter)), "Spread's parent is not a chapter"); // Find top left of chapter pasteboard DocRect ChapterRect = pChapter->GetPasteboardRect(TRUE, pView); ChapterPos.x = ChapterRect.lo.x; ChapterPos.y = ChapterRect.hi.y; // Find chapter depth ChapterDepth = pChapter->GetChapterDepth(); // This builds the 64-bit conversion matrix needed for Document To WorkArea // coordinate mappings. ConvertToWorkMat = ComposeDocToWorkXMat(ChapterPos, ChapterDepth, pView->GetViewScale()); // Apply the matrix to the DocCoord... ConvertToWorkMat.transform(&WrkPoint, 1); return (WrkPoint); } WorkCoord DocCoord::ToLogical(Spread* pSpread, View *pView) { // Check that we have not been fed garbage ENSURE( pSpread!=NULL, "DocCoord::ToLogical was passed a NULL spread" ); // Find the chapter Chapter* pChapter = (Chapter*) pSpread->FindParent(); ENSURE( pChapter!=NULL, "DocCoord::ToLogical. Spread did not have a parent chapter" ); ENSURE( pChapter->IsKindOf(CC_RUNTIME_CLASS(Chapter)), "DocCoord::ToLogical. Chapter is not a chapter" ); // Find out about the chapter DocRect ChapterRect = pChapter->GetPasteboardRect(TRUE, pView); XLONG ChapterDepth = pChapter->GetChapterDepth(); // Build the logical coord from the doccoord WorkCoord Result( MakeXLong(x), MakeXLong(y) ); Result.x = Result.x - ChapterRect.lo.x; Result.y = Result.y - ChapterRect.hi.y; Result.y = Result.y - ChapterDepth; // return the coord return Result; } /*********************************************************************************************** > DocCoord DocCoord::ToSpread(Spread* pSpread, View* pView) Author: Ed_Cornes (Xara Group Ltd) Created: 5/9/95 Inputs: pSpread - pView - Returns: SpreadCoord Purpose: Convert DocCoord to a SpreadCoord SeeAlso: Spread::SpreadCoordToDocCoord *********************************************************************************************/ DocCoord DocCoord::ToSpread(Spread* pSpread, View* pView) { ERROR3IF((pSpread==NULL || pView==NULL), "DocCoord::ToSpread() - pSpread==NULL || pView==NULL"); DocCoord temp(x, y); if (pSpread != NULL) pSpread->DocCoordToSpreadCoord(&temp); return(temp); } /*********************************************************************************************** > DocCoord DocCoord::ToDoc(Spread* pSpread, View* pView) Author: Ed_Cornes (Xara Group Ltd) Created: 5/9/95 Inputs: pSpread - pView - Returns: SpreadCoord Purpose: Convert SpreadCoord to a DocCoord SeeAlso: Spread::SpreadCoordToDocCoord *********************************************************************************************/ DocCoord DocCoord::ToDoc(Spread* pSpread, View* pView) { ERROR3IF(pSpread == NULL || pView == NULL, "DocCoord::ToDoc() - pSpread==NULL || pView==NULL"); DocCoord temp(x, y); if (pSpread != NULL) pSpread->SpreadCoordToDocCoord(&temp); return(temp); } /*********************************************************************************************** > UserCoord DocCoord::ToUser(Spread* pSpread) Author: Ed_Cornes (Xara Group Ltd) Created: 11/9/95 Inputs: pSpread - Returns: UserCoord Purpose: Convert SpreadCoord to a UserCoord *********************************************************************************************/ UserCoord DocCoord::ToUser(Spread* pSpread) { DocCoord UserOrigin(0,0); if (pSpread!=NULL) UserOrigin=pSpread->GetUserOrigin(); else ERROR3("DocCoord::ToUser() - pSpread==NULL"); return UserCoord(this->x-UserOrigin.x, this->y-UserOrigin.y); } /*********************************************************************************************** > OilCoord DocCoord::ToOil(Spread* pSpread, View* pView) Author: Ed_Cornes (Xara Group Ltd) Created: 11/9/95 Inputs: pSpread - pView - Returns: OilCoord Purpose: Convert SpreadCoord (AKA DocCoord) to an OilCoord *********************************************************************************************/ OilCoord DocCoord::ToOil(Spread* pSpread, View* pView) { WorkCoord ScrollOffsets(0,0); if (pView!=NULL) ScrollOffsets=pView->GetScrollOffsets(); else ERROR3("DocCoord::ToOil() - pView==NULL"); return ToDoc(pSpread,pView).ToWork(pSpread,pView).ToOil(ScrollOffsets); } /*********************************************************************************************** > Chapter* DocCoord::FindEnclosingChapter(Document *pDocument, DocCoord* ChapterPos, XLONG* ChapterDepth); Author: Simon_Maneggio (Xara Group Ltd) Created: 30/4/93 Inputs: pDocument - the document we are converting in. pView - the View to use for pixelising. Outputs: ChapterPos: The top left hand corner of the chapters pasteboard rectangle ChapterDepth: The Sum of the lengths of all preceding chapters Returns: If this coord is enclosed within a chapter then the chapter is returned else NULL is returned (In the non DEBUG version). Purpose: For finding the enclosing chapter of a DocCoord, the position of the start of the enclosing chapter, and the chapters depth. Scope: Private Errors: An ERROR3 will occur if the DocCoord is not in any chapter NOTE: The Spread Coordinate Origin for a spread MAY NOT reside INSIDE a Chapter's Pasteboard bounds! See Spread::GetSpreadCoordOrigin for full details of this. SeeAlso: - *********************************************************************************************/ Chapter* DocCoord::FindEnclosingChapter(Document *pDocument, DocCoord* ChapterPos, XLONG* ChapterDepth, View *pView) { Chapter* CurrentChapter = Node::FindFirstChapter(pDocument); // Search all chapters *ChapterDepth = 0; DocRect CurrentChaptersPasteboardRect; while (CurrentChapter != NULL) { CurrentChaptersPasteboardRect = CurrentChapter->GetPasteboardRect(TRUE, pView); if (CurrentChaptersPasteboardRect.ContainsRectCoord(*this)) { // Chapter position is the top left hand corner of the chapters pasteboard ChapterPos->x = CurrentChaptersPasteboardRect.LowCorner().x; ChapterPos->y = CurrentChaptersPasteboardRect.HighCorner().y; return (CurrentChapter); } (*ChapterDepth) += CurrentChaptersPasteboardRect.Height(); CurrentChapter = CurrentChapter->FindNextChapter(); } // The DocCoord was not found in any chapter ERROR3("DocCoord::FindEnclosingChapter: Coord wasn't in any chapter. See the function help for debugging tips"); return(NULL); } /********************************************************************************************* > BOOL DocCoord::Pixelise(View* pView) Author: Phil_Martin (Xara Group Ltd) Created: 21/11/94 Inputs: The view we are pixelising for. Purpose: Modifies this DocCoord to lie on an exact pixel boundary. Scope: Public SeeAlso: DocCoord::SetScaledPixelSize() **********************************************************************************************/ /* Technical notes: This routine ensures that the coordinate is aligned to a whole pixel boundary at all times by dividing and re-multiplying by the pixel size (YUK). Note that when a negative value is divided in C++ it is done so without regard for the sign of the value. E.g. 21 / 4 = 5 Result has been truncated towards 0, moving Y coordinates down -21/ 4 = -5 Result has been truncated towards 0 again, moving Y coordinates UP!!! In other words when the values are coordinates the division truncates them in different directions depending which side of the origin they are on! This is obviously not required and so any negative values are adjusted before the division to ensure the end result is movement in the same direction as positive values. Range of scaled pixel width/height: Min: ScaledPixelsize = 1(millipoint) / 40 (4000%) = 0.025 Max: ScaledPixelSize = 2000 (1/36th of an inch) / 0.05 (5%) = 40,000 These values fit nicely into a Fixed16 so they should be correct on the way into the pixelising maths. However, Fixed16s cannot be combined with INT32s easily and they would not be accuarate enough to hold the possible pixel values. So, the pixelising maths is all done using floating point doubles. ********************************************************************************************/ BOOL DocCoord::Pixelise(View* pView) { // See if the view is ok if (pView==NULL) return FALSE; FIXED16 pw,ph; pView->GetScaledPixelSize(&pw,&ph); x = (INT32) ( (floor(0.5 + (double)x / pw.MakeDouble())) * pw.MakeDouble() ); y = (INT32) ( (floor(0.5 + (double)y / ph.MakeDouble())) * ph.MakeDouble() ); return TRUE; } /********************************************************************************************* > BOOL DocCoord::IsPixelised(View* pView) Author: Phil_Martin (Xara Group Ltd) Created: 21/11/94 Inputs: The view we are pixelising for. Outputs: - Returns: TRUE if this DocCoord is already pixelised FALSE otherwise Purpose: Modifies this DocCoord to lie on an exact pixel boundary. Scope: Public **********************************************************************************************/ BOOL DocCoord::IsPixelised(View* pView) { // See if the view is ok if (pView==NULL) return FALSE; // Now pixelise a temp copy of this coord and see if it changed at all... DocCoord temp(x,y); temp.Pixelise(pView); return (x==temp.x && y==temp.y); } /********************************************************************************************* > static BOOL DocCoord::Pixelise() Author: Phil_Martin (Xara Group Ltd) Created: 21/11/94 Inputs: - Outputs: - Returns: - Purpose: Modifies this DocCoord to lie on an exact pixel boundary. Errors: - Scope: Public SeeAlso: DocCoord::SetScaledPixelSize() **********************************************************************************************/ // NB. This is a bodge until I fix all the callers of Pixelise to pass in the View (Tim). BOOL DocCoord::Pixelise() { // BODGE: ...until I can be bothered to get callers to pass view in... (Tim) return Pixelise(View::GetCurrent()); } #endif // EXCLUDE_FROM_XARLIB /******************************************************************************************** > DocCoord operator + (const DocCoord& One, const DocCoord& Two) Author: Peter_Arnold (Xara Group Ltd) Created: 15/12/94 Inputs: One - The first DocCoord Two - The second DocCoord Returns: The result of adding the two DocCoords together. Purpose: Adds two DocCoords together. ie One.x+Two.x, One.y+Two.y ********************************************************************************************/ DocCoord operator + (const DocCoord& One, const DocCoord& Two) { DocCoord Result; // Add the two DocCoords together Result.x = One.x + Two.x; Result.y = One.y + Two.y; // return the result return Result; } /******************************************************************************************** > DocCoord operator - (const DocCoord& One, const DocCoord& Two) Author: Peter_Arnold (Xara Group Ltd) Created: 15/12/94 Inputs: One - The first DocCoord Two - The second DocCoord Returns: the DocCoord that is the first DocCoord minus the second DocCoord Purpose: Subtracts the two DocCoords. ie One.x-Two.x, One.y-Two.y ********************************************************************************************/ DocCoord operator - (const DocCoord& One, const DocCoord& Two) { DocCoord Result; // Subtract the two DocCoords from each other Result.x = One.x - Two.x; Result.y = One.y - Two.y; // return the result return Result; } /******************************************************************************************** > const DocCoord& DocCoord::operator += ( const DocCoord &Other ) Author: Graeme_Sutherland (Xara Group Ltd) Created: 29/4/00 Inputs: Other - The other DocCoord value, that's being added to the original. Returns: A reference to the current object, for concatentation Purpose: Adds a DocCoord value onto the current object. ********************************************************************************************/ const DocCoord& DocCoord::operator += ( const DocCoord &Other ) { // Add the other DocCoord's values onto this object's. x += Other.x; y += Other.y; return *this; } /******************************************************************************************** > const DocCoord& DocCoord::operator -= ( const DocCoord &Other ) Author: Graeme_Sutherland (Xara Group Ltd) Created: 29/4/00 Inputs: Other - The other DocCoord value, that's being subtracted from this one. Returns: A reference to the current object, for concatentation Purpose: Subtracts a DocCoord value from the current object. ********************************************************************************************/ const DocCoord& DocCoord::operator -= ( const DocCoord &Other ) { // Add the other DocCoord's values onto this object's. x -= Other.x; y -= Other.y; return *this; } /******************************************************************************************* > static DocCoord DocCoord::PositionPointFromRatio(const DocCoord& StartPoint, const DocCoord& EndPoint, const double Ratio) Author: Peter_Arnold (Xara Group Ltd) Created: 12/12/95 Inputs: StartPoint and EndPoint define the start and end of a line Ratio is the ratio of the distance from start to end that you want the coordinate of Outputs: - Returns: The coordinate of the position of the ratio (err, does that make sense?) Purpose: Gives the coordinate of a point specified by a ratio along a line defined by two other points. A ratio of zero gives the same point as the start of the line, 0.5 gives the mid point of the line, etc. Negative ratio give a point before the start, ratios greater than 1 give points beyond the end ********************************************************************************************/ DocCoord DocCoord::PositionPointFromRatio(const DocCoord& StartPoint, const DocCoord& EndPoint, const double Ratio) { DocCoord result; result.x = StartPoint.x + (INT32)((EndPoint.x - StartPoint.x)*Ratio) ; result.y = StartPoint.y + (INT32)((EndPoint.y - StartPoint.y)*Ratio) ; return result; } /******************************************************************************************* > static double DocCoord::DistanceFromLine(const DocCoord& Line1, const DocCoord& Line2, const DocCoord& Point) Author: Peter_Arnold (Xara Group Ltd) Created: 12/12/95 Inputs: Line1 and Line2 are two points defining a line that passes through those points Point is another point Outputs: - Returns: The perpendicular distance from the line to the point. Purpose: Gets the shortest distance from the line to the point. Errors: Will return -1 if a division by zero case was detected ********************************************************************************************/ double DocCoord::DistanceFromLine(const DocCoord& Line1, const DocCoord& Line2, const DocCoord& Point) { // Obtain perpendicular distance from the axes line (see A-Level maths page 24) const double X1 = Line1.x; const double Y1 = Line1.y; const double X2 = Line2.x; const double Y2 = Line2.y; const double a = -Y2+Y1; const double b = X2-X1; const double c = -(Y1*X2) + (Y1*X1) + (X1*Y2) - (X1*Y1); const double divisor = sqrt( a*a + b*b ); // We don't want any nasty floating point div 0, thank you double Distance = -1.0; if (divisor >= 0.0001) Distance = fabs(( a*Point.x + b*Point.y + c )/divisor); return Distance; } /******************************************************************************************* > static DocCoord DocCoord::OneThird(const DocCoord& Start, const DocCoord& End) Author: Peter_Arnold (Xara Group Ltd) Created: 12/12/95 Inputs: Start and End are two coordinates Outputs: - Returns: The point one third of the way from Start to End Purpose: For getting a point one third of the way between two other points ********************************************************************************************/ DocCoord DocCoord::OneThird(const DocCoord& Start, const DocCoord& End) { DocCoord result; result.x = Start.x + (INT32)((End.x - Start.x)/3) ; result.y = Start.y + (INT32)((End.y - Start.y)/3) ; return result; } /******************************************************************************************* > static DocCoord DocCoord::TwoThirds(const DocCoord& Start, const DocCoord& End) Author: Peter_Arnold (Xara Group Ltd) Created: 12/12/95 Inputs: Start and End are two coordinates Outputs: - Returns: The point two thirds of the way from Start to End Purpose: For getting a point two thirds of the way between two other points ********************************************************************************************/ DocCoord DocCoord::TwoThirds(const DocCoord& Start, const DocCoord& End) { DocCoord result; result.x = Start.x + (INT32)((End.x - Start.x)*(2.0/3.0)) ; result.y = Start.y + (INT32)((End.y - Start.y)*(2.0/3.0)) ; return result; } /******************************************************************************************* > static DocCoord DocCoord::OneHalf(const DocCoord& Start, const DocCoord& End) Author: Peter_Arnold (Xara Group Ltd) Created: 12/12/95 Inputs: Start and End are two coordinates Outputs: - Returns: The point one half of the way from Start to End Purpose: For getting a point midway between two other points ********************************************************************************************/ DocCoord DocCoord::OneHalf(const DocCoord& Start, const DocCoord& End) { DocCoord result; result.x = Start.x + (INT32)((End.x - Start.x)/2) ; result.y = Start.y + (INT32)((End.y - Start.y)/2) ; return result; } /******************************************************************************************** > BOOL DocCoord::IsJoinAcute(const DocCoord* pJoin, const DocCoord* pOtherEndOfJoin, const DocCoord* pOtherPoint) Author: Peter_Arnold (Xara Group Ltd) Created: 13/12/95 Inputs: pJoin - the coordinate where two lines join pOtherEndOfJoin - another point that with pJoin defines a line pOtherPoint - another point that with pJoin defines another line Outputs: - Returns: TRUE if the angle between the two lines is an acute angle Purpose: For seeing the perpendicual distance from pOtherPoint to the line pJoin-pOtherEndOfJoin end on the line or before pJoin. Used when dragging along a line to see if the drag point has gon back beyond the start of the line. ********************************************************************************************/ BOOL DocCoord::IsJoinAcute(const DocCoord* pJoin, const DocCoord* pOtherEndOfJoin, const DocCoord* pOtherPoint) { // Translate the points so the join is on the origin and the other points are relative to that DocCoord OriginLine = *pOtherEndOfJoin - *pJoin; DocCoord OriginOther = *pOtherPoint - *pJoin; double LineAngle = atan2((double)OriginLine.y, (double)OriginLine.x); double OtherAngle = atan2((double)OriginOther.y, (double)OriginOther.x); double diff = OtherAngle - LineAngle; if (diff < -PI) diff += 2*PI; if (diff > PI) diff -= 2*PI; if ( (diff < -(PI/2)) || (diff > (PI/2)) ) return FALSE; else return TRUE; } /******************************************************************************************** > void DocCoord::Scale(const DocCoord dcOrigin, const double dDPI=96.0) Author: Graham_Walmsley (Xara Group Ltd) Created: 16/4/97 Inputs: dDPI The DPI by which to scale the coord dcOrigin The origin by which to scale the coord Purpose: Scales the DocCoord by the specified DPI and origin. That is, this function does the following to this DocCoord: a. Subtracts the origin dcOrigin b. Inverts the y-axis c. Multiplies the coordinate to convert them to the number of DPI specified. Used in imagemaps. Note that, technically, what this function produces should be a WorkCoord. But that causes problems, because this function is called to scale paths to bitmap coordinates - and you can't specify a path in terms of WorkCoords. SeeAlso: Path::Scale(), Imagemap::AddPolygon() ********************************************************************************************/ void DocCoord::Scale(const DocCoord dcOrigin, const double dDPI) { //Subtract the origin from this coord x-=dcOrigin.x; y-=dcOrigin.y; //And scale by the appropriate DPI, inverting the y-axis //and rounding to the nearest pixel x=INT32(x*(dDPI/72000.0)+0.5); y=INT32(-y*(dDPI/72000.0)+0.5); }