00001 // $Id: samplist.cpp 1282 2006-06-09 09:46:49Z alex $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 00099 // CSampleList and CSampleItem implementation 00100 00101 #include "camtypes.h" 00102 #include "samplist.h" 00103 #include "brshcomp.h" 00104 //#include "cxfrec.h" - in camtypes.h [AUTOMATICALLY REMOVED] 00105 #include "pen.h" 00106 00107 CC_IMPLEMENT_DYNAMIC(CSampleItem, CCObject); 00108 CC_IMPLEMENT_DYNAMIC(CSampleData, CCObject); 00109 CC_IMPLEMENT_DYNAMIC(CDistanceSampler, CSampleData); 00110 00111 const double MIN_COLLECTION_SAMPLE_RATE = 1.0; 00112 const double MAX_COLLECTION_SAMPLE_RATE = 1.0; 00113 const double MIN_RETRIEVAL_SAMPLE_RATE = 1.0; 00114 const double MAX_RETRIEVAL_SAMPLE_RATE = 10000.0; 00115 00116 /*------------------------------------------------------------------------------------------- 00117 ------------------------------CSampleItem implementation------------------------------------- 00118 --------------------------------------------------------------------------------------------- 00119 */ 00120 00121 /******************************************************************************************** 00122 00123 > CSampleItem::CSampleItem() 00124 00125 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00126 Created: 31/5/2000 00127 Inputs: - 00128 Outputs: - 00129 Returns: this object 00130 Purpose: default constructor 00131 00132 Notes: 00133 ********************************************************************************************/ 00134 00135 CSampleItem::CSampleItem() 00136 { 00137 m_Distance = 0; 00138 m_Coord.x = m_Coord.y = 0; 00139 m_Pressure = 0; 00140 } 00141 00142 00143 /******************************************************************************************** 00144 00145 > CSampleItem::CSampleItem() 00146 00147 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00148 Created: 31/5/2000 00149 Inputs: Coord - the position of this sample 00150 Distance - the distance along the path of this sample 00151 Outputs: - 00152 Returns: this object 00153 Purpose: constructor with initialisation 00154 00155 Notes: 00156 ********************************************************************************************/ 00157 00158 CSampleItem::CSampleItem(DocCoord Coord, MILLIPOINT Distance, UINT32 Pressure) 00159 { 00160 m_Coord = Coord; 00161 m_Distance = Distance; 00162 m_Pressure = Pressure; 00163 00164 } 00165 00166 00167 /******************************************************************************************** 00168 00169 > CSampleItem::CSampleItem() 00170 00171 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00172 Created: 31/5/2000 00173 Inputs: Other - another CSampleItem 00174 Outputs: - 00175 Returns: this object 00176 Purpose: copy constructor 00177 00178 Notes: 00179 ********************************************************************************************/ 00180 00181 CSampleItem::CSampleItem(const CSampleItem& Other) 00182 { 00183 m_Distance = Other.m_Distance; 00184 m_Coord = Other.m_Coord; 00185 m_Pressure = Other.m_Pressure; 00186 00187 } 00188 00189 00190 00191 /******************************************************************************************** 00192 00193 > CSampleItem CSampleItem::operator =(CSampleItem& Other) 00194 00195 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00196 Created: 31/5/2000 00197 Inputs: Other - another CSampleItem 00198 Outputs: - 00199 Returns: this object 00200 Purpose: assignment operator 00201 00202 Notes: 00203 ********************************************************************************************/ 00204 00205 CSampleItem CSampleItem::operator =(const CSampleItem& Other) 00206 { 00207 m_Coord = Other.m_Coord; 00208 m_Distance = Other.m_Distance; 00209 m_Pressure = Other.m_Pressure; 00210 return *this; 00211 } 00212 00213 00214 00215 /******************************************************************************************** 00216 00217 > BOOL CSampleItem::operator ==(CSampleItem& Other) 00218 00219 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00220 Created: 31/5/2000 00221 Inputs: Other - another CSampleItem 00222 Outputs: - 00223 Returns: TRUE if the objects are identical, FALSE if they are not 00224 Purpose: equality operator 00225 00226 Notes: 00227 ********************************************************************************************/ 00228 00229 BOOL CSampleItem::operator ==(const CSampleItem& Other) 00230 { 00231 BOOL bDiff = (m_Coord != Other.m_Coord || 00232 m_Distance != Other.m_Distance || 00233 m_Pressure != Other.m_Pressure); 00234 return bDiff; 00235 } 00236 00237 /******************************************************************************************** 00238 00239 > BOOL CSampleItem::operator ==(CSampleItem& Other) 00240 00241 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00242 Created: 31/5/2000 00243 Inputs: Other - another CSampleItem 00244 Outputs: - 00245 Returns: TRUE if the objects are identical, FALSE if they are not 00246 Purpose: equality operator 00247 00248 Notes: 00249 ********************************************************************************************/ 00250 00251 CSampleItem CSampleItem::InterpolateItems(CSampleItem& Other, double Proportion) 00252 { 00253 CSampleItem NewItem; 00254 00255 if (Proportion < 0.0 || Proportion > 1.0) 00256 { 00257 ERROR3("Invalid proportion value in CSampleItem::InterpolateItems"); 00258 return NewItem; 00259 } 00260 00261 NewItem.m_Distance = (INT32)(((double)m_Distance * Proportion) + ((double)Other.m_Distance * (1-Proportion))); 00262 MILLIPOINT XVal = (INT32)((m_Coord.x * Proportion) + (Other.m_Coord.x * (1 - Proportion))); 00263 MILLIPOINT YVal = (INT32)((m_Coord.y * Proportion) + (Other.m_Coord.y * (1 - Proportion))); 00264 00265 NewItem.m_Coord.x = XVal; 00266 NewItem.m_Coord.y = YVal; 00267 00268 NewItem.m_Pressure = (UINT32)((m_Pressure * Proportion) + (Other.m_Pressure * (1-Proportion))); 00269 00270 return NewItem; 00271 } 00272 00273 /******************************************************************************************** 00274 00275 00276 > BOOL CSampleItem::WriteNative(CXaraFileRecord* pRecord) 00277 00278 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00279 Created: 13/12/99 00280 Inputs: pRecord - the record to write to 00281 Returns: TRUE if the Node has written out a record to the filter 00282 Purpose: Writes this sampledata item to a record 00283 00284 SeeAlso: CSampleData::WriteNative 00285 00286 ********************************************************************************************/ 00287 00288 BOOL CSampleItem::WriteNative(CXaraFileRecord* pRecord) 00289 { 00290 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL in CSampleItem::WriteNative"); 00291 00292 BOOL ok = pRecord->WriteINT32((INT32)m_Pressure); 00293 if (ok) ok = pRecord->WriteCoord(m_Coord); 00294 if (ok) ok = pRecord->WriteINT32(m_Distance); 00295 00296 return ok; 00297 } 00298 00299 /*------------------------------------------------------------------------------------------- 00300 ------------------------------CSampleData implementation------------------------------------- 00301 --------------------------------------------------------------------------------------------- 00302 */ 00303 00304 /******************************************************************************************** 00305 00306 > CSampleData::CSampleData() 00307 00308 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00309 Created: 31/5/2000 00310 Inputs: - 00311 Outputs: - 00312 Returns: this object 00313 Purpose: default constructor 00314 00315 Notes: 00316 ********************************************************************************************/ 00317 00318 CSampleData::CSampleData() 00319 { 00320 m_pSampleData = NULL; 00321 m_CollectionSampleRate = 1.0; 00322 m_RetrievalSampleRate = 1.0; 00323 m_CollectionInternalIndex = 0; 00324 m_RetrievalInternalIndex = 0; 00325 m_NumItems = 0; 00326 m_MaxPressure = 0; 00327 m_ElementSize = (UINT32)sizeof(CSampleItem); 00328 } 00329 00330 00331 /******************************************************************************************** 00332 00333 > CSampleData::~CSampleData() 00334 00335 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00336 Created: 31/5/2000 00337 Inputs: - 00338 Outputs: - 00339 Returns: - 00340 Purpose: destructor, cleans out the list 00341 00342 Notes: 00343 ********************************************************************************************/ 00344 00345 CSampleData::~CSampleData() 00346 { 00347 if (m_pSampleData != NULL) 00348 { 00349 m_pSampleData->clear(); 00350 delete m_pSampleData; 00351 m_pSampleData = NULL; 00352 } 00353 } 00354 00355 00356 /******************************************************************************************** 00357 00358 > CSampleData* CSampleData::MakeCopy(CSampleData* pOther) 00359 00360 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00361 Created: 31/5/2000 00362 Inputs: - 00363 Outputs: - 00364 Returns: a copy of this object, unless something goes wrong (i.e memory) in which case NULL 00365 Purpose: Makes a copy of this sample data. 00366 00367 Notes: 00368 ********************************************************************************************/ 00369 00370 CSampleData* CSampleData::MakeCopy() 00371 { 00372 CSampleData* pNewData = new CSampleData; 00373 00374 if (pNewData == NULL) 00375 return NULL; 00376 00377 if (!pNewData->InitialiseData(m_NumItems)) 00378 { 00379 delete pNewData; 00380 return NULL; 00381 } 00382 00383 m_RetrievalSampleRate = 1; // make sure we get all the items 00384 00385 CSampleItem TheItem; 00386 00387 // unfortunately my implementation is a bit clumsy so we have to do the first item 00388 // by hand 00389 BOOL Getok = GetAt(0, &TheItem); 00390 BOOL Setok = pNewData->SetAt(0, TheItem); 00391 //TRACEUSER( "Diccon", _T("Copying pressure %d\n"), TheItem.m_Pressure); 00392 if (Getok == FALSE || Setok == FALSE) 00393 ERROR3("Failed to get or set first item in CSampleData::MakeCopy"); 00394 00395 UINT32 Counter = 1; 00396 // now we can loop through the rest 00397 while (Getok && Setok) 00398 { 00399 Getok = GetNext(&TheItem); 00400 Setok = pNewData->SetNext(TheItem); 00401 //TRACEUSER( "Diccon", _T("Copying pressure %d\n"), TheItem.m_Pressure); 00402 Counter++; 00403 } 00404 00405 if (Counter != m_NumItems) 00406 TRACEUSER( "Diccon", _T("CSampleData::MakeCopy - Num items copied = %d, Actual num items = %d\n"), Counter, m_NumItems); 00407 00408 return pNewData; 00409 } 00410 00411 /******************************************************************************************** 00412 00413 > BOOL CSampleData::InitialiseData(UINT32 Size, UINT32 GrowBy) 00414 00415 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00416 Created: 31/5/2000 00417 Inputs: - 00418 Outputs: - 00419 Returns: TRUE if we initialised ok, FALSE if we didn't get the memory 00420 Purpose: creates the list member variable 00421 00422 Notes: 00423 ********************************************************************************************/ 00424 00425 BOOL CSampleData::InitialiseData( size_t Size, UINT32 GrowBy ) 00426 { 00427 // if we've already got a list then delete it 00428 if (m_pSampleData != NULL) 00429 { 00430 m_pSampleData->clear(); 00431 delete m_pSampleData; 00432 m_pSampleData = NULL; 00433 } 00434 m_pSampleData = new SampleArray; 00435 00436 if (m_pSampleData == NULL) 00437 return FALSE; 00438 00439 if( Size < m_pSampleData->size() + GrowBy ) 00440 Size = m_pSampleData->size() + GrowBy; 00441 00442 m_pSampleData->resize( Size ); 00443 00444 return TRUE; 00445 } 00446 00447 00448 /******************************************************************************************** 00449 00450 > BOOL CSampleData::CollectData(DocCoord Coord, UINT32 Pressure) 00451 00452 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00453 Created: 31/5/2000 00454 Inputs: Coord - the coordinate data 00455 Pressure - the pressure data 00456 Outputs: - 00457 Returns: always TRUE in the base class 00458 Purpose: This is the function you should override in you derived classes to do the sampling 00459 with. For an example see CDistanceSampler::CollectData 00460 00461 Notes: 00462 ********************************************************************************************/ 00463 00464 BOOL CSampleData::CollectData(DocCoord Coord, UINT32 Pressure) 00465 { 00466 return TRUE; 00467 } 00468 00469 /*------------------------------------------------------------------------------------------- 00470 -------------------------Array access functions----------------------------------------------- 00471 --------------------------------------------------------------------------------------------*/ 00472 00473 00474 /******************************************************************************************** 00475 00476 > void CSampleData::Add(CSampleItem& Item) 00477 00478 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00479 Created: 31/5/2000 00480 Inputs: Item - the item to insert 00481 Outputs: - 00482 Returns: - 00483 Purpose: adds a new item to the end of the array 00484 00485 Notes: 00486 ********************************************************************************************/ 00487 00488 void CSampleData::Add(CSampleItem& Item) 00489 { 00490 if (m_pSampleData != NULL) 00491 m_pSampleData->push_back(Item); 00492 m_NumItems++; 00493 00494 } 00495 00496 /******************************************************************************************** 00497 00498 > BOOL CSampleData::SetAt(UINT32 Index CSampleItem& Item) 00499 00500 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00501 Created: 31/5/2000 00502 Inputs: Index - the position to set Item at 00503 Item - the item to insert 00504 Outputs: - 00505 Returns: TRUE if successful, FALSE otherwise 00506 Purpose: inserts Item at Index 00507 00508 Notes: Currently it is not permitted to Set, Remove or Insert items if the sample rate is not 1. 00509 This is because a) I really don't want people changing data in the array once 00510 it has been collected (we're sampling remember) and b) Its a pain in the ass 00511 ********************************************************************************************/ 00512 00513 BOOL CSampleData::SetAt(UINT32 Index, CSampleItem& Item) 00514 { 00515 BOOL Retval = FALSE; 00516 if (m_pSampleData != NULL) 00517 { 00518 // we are not allowed to be setting data when the sample rate is not 1.0 00519 if (m_CollectionSampleRate < MIN_COLLECTION_SAMPLE_RATE || 00520 m_CollectionSampleRate > MAX_COLLECTION_SAMPLE_RATE) 00521 { 00522 ERROR3("Attempting to set data when SampleRate != 1"); 00523 return FALSE; 00524 } 00525 if (SetInternalCollectionIndex(Index)) 00526 { 00527 (*m_pSampleData)[size_t(m_CollectionInternalIndex)] = Item; 00528 Retval = TRUE; 00529 if ((UINT32)m_CollectionInternalIndex > m_NumItems) 00530 m_NumItems = (UINT32)m_CollectionInternalIndex; 00531 } 00532 else 00533 ERROR3("Attempting to set over the end of the array in CSampleData::SetAt"); 00534 } 00535 return Retval; 00536 } 00537 00538 /******************************************************************************************** 00539 00540 > BOOL CSampleData::SetNext(CSampleItem& Item, BOOL Grow) 00541 00542 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00543 Created: 31/5/2000 00544 Inputs: Item - the item to insert 00545 Grow - do we wish to grow the array if we hit the end (defaults to FALSE) 00546 Outputs: - 00547 Returns: TRUE, unless we hit the end of the array and do not widh to grow 00548 Purpose: Increments our internal index and then inserts a new item at that position. 00549 If we hit the end of the array then we will add an element, so long as our flag 00550 is set 00551 Notes: 00552 ********************************************************************************************/ 00553 00554 BOOL CSampleData::SetNext(CSampleItem& Item, BOOL Grow) 00555 { 00556 BOOL Retval = FALSE; 00557 if (m_pSampleData != NULL) 00558 { 00559 // we are not allowed to be setting data when the sample rate is not 1.0 00560 if (m_CollectionSampleRate < MIN_COLLECTION_SAMPLE_RATE || 00561 m_CollectionSampleRate > MAX_COLLECTION_SAMPLE_RATE) 00562 { 00563 ERROR3("Attempting to set data when SampleRate != 1"); 00564 return FALSE; 00565 } 00566 if (IncrementInternalIndex(&m_CollectionInternalIndex)) 00567 { 00568 // if internal index == -1 after incrementing it means we hit the end of the array 00569 if (m_CollectionInternalIndex != -1.0) 00570 { 00571 //TRACEUSER( "Diccon", _T("Setting at %f\n"), m_CollectionInternalIndex); 00572 (*m_pSampleData)[size_t(m_CollectionInternalIndex)] = Item; 00573 Retval = TRUE; 00574 if ((UINT32)m_CollectionInternalIndex > m_NumItems) 00575 m_NumItems = (UINT32)m_CollectionInternalIndex; 00576 } 00577 else 00578 { 00579 // we must have hit the end of the array, so we need to add 00580 if (Grow == TRUE) 00581 { 00582 m_pSampleData->push_back( Item ); 00583 Retval = TRUE; 00584 m_NumItems++; 00585 m_CollectionInternalIndex = m_NumItems; 00586 } 00587 } 00588 } 00589 else 00590 ERROR3("Failed to increment index in CSampleData::SetNext"); 00591 } 00592 00593 return Retval; 00594 } 00595 00596 /******************************************************************************************** 00597 00598 > BOOL CSampleData::SetPrev(CSampleItem& Item) 00599 00600 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00601 Created: 31/5/2000 00602 Inputs: Item - the item to insert 00603 Outputs: - 00604 Returns: TRUE if successful, FALSE if we're already at the head of the array 00605 Purpose: Decrements our internal index and then inserts Item into the array. 00606 00607 Notes: 00608 ********************************************************************************************/ 00609 00610 BOOL CSampleData::SetPrev(CSampleItem& Item) 00611 { 00612 BOOL Retval = FALSE; 00613 if (m_pSampleData != NULL) 00614 { 00615 // we are not allowed to be setting data when the sample rate is not 1.0 00616 if (m_CollectionSampleRate < MIN_COLLECTION_SAMPLE_RATE || 00617 m_CollectionSampleRate > MAX_COLLECTION_SAMPLE_RATE) 00618 { 00619 ERROR3("Attempting to set data when SampleRate != 1"); 00620 return Retval; 00621 } 00622 if (DecrementInternalIndex(&m_CollectionInternalIndex)) 00623 { 00624 if (m_CollectionInternalIndex != -1.0) 00625 { 00626 (*m_pSampleData)[size_t(m_CollectionInternalIndex)] = Item; 00627 Retval = TRUE; 00628 } 00629 else 00630 ERROR3("Attempting to SetPrev over the start of the array in CSampleData::SetPrev"); 00631 } 00632 ERROR3("Unable to decrement index in CSampleData::SetPrev"); 00633 } 00634 return Retval; 00635 } 00636 00637 /******************************************************************************************** 00638 00639 > BOOL CSampleData::RemoveAt(UINT32 Index) 00640 00641 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00642 Created: 31/5/2000 00643 Inputs: Index - the position to remove from 00644 Outputs: - 00645 Returns: TRUE, unless we go over the end of the array 00646 Purpose: Removes item at Index 00647 00648 Notes: 00649 ********************************************************************************************/ 00650 00651 BOOL CSampleData::RemoveAt(UINT32 Index) 00652 { 00653 BOOL Retval = FALSE; 00654 if (m_pSampleData != NULL) 00655 { 00656 // we are not allowed to be setting data when the sample rate is not 1.0 00657 if (m_CollectionSampleRate < MIN_COLLECTION_SAMPLE_RATE || 00658 m_CollectionSampleRate > MAX_COLLECTION_SAMPLE_RATE) 00659 { 00660 ERROR3("Attempting to remove data when SampleRate != 1"); 00661 return FALSE; 00662 } 00663 if (SetInternalRetrievalIndex(Index)) 00664 { 00665 m_pSampleData->erase( m_pSampleData->begin() + size_t(m_RetrievalInternalIndex) ); 00666 Retval = TRUE; 00667 m_NumItems--; 00668 } 00669 else 00670 ERROR3("Attempting to remove beyond the end of the array in CSampleData::RemoveAt"); 00671 } 00672 return Retval; 00673 } 00674 00675 00676 00677 00678 /******************************************************************************************** 00679 00680 > BOOL CSampleData::GetAt(UINT32 Index, CSampleItem* pItem) 00681 00682 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00683 Created: 31/5/2000 00684 Inputs: Index - the index to retrieve from 00685 Outputs: pItem - the item at index 00686 Returns: TRUE if successful, FALSE if Index is invalid or there is no array 00687 Purpose: Retrieves the item at Index 00688 00689 Notes: All the access functions set the m_ListPosition member variable which records 00690 the last list positon accessed. This means that you can the use GetNext or 00691 GetPrev to retrieve subsequent elements, which is much quicker than using 00692 GetAt all the time. 00693 ********************************************************************************************/ 00694 00695 BOOL CSampleData::GetAt(UINT32 Index, CSampleItem* pItem) 00696 { 00697 ERROR2IF(pItem == NULL, FALSE, "Item pointer is NULL in CSampleData::GetAt"); 00698 00699 if (m_pSampleData != NULL) 00700 { 00701 if (SetInternalRetrievalIndex(Index)) 00702 { 00703 //TRACEUSER( "Diccon", _T("Get At: ")); 00704 CSampleItem TheItem; 00705 if (GetItemAtInternalIndex(m_RetrievalInternalIndex, &TheItem)) 00706 *pItem = TheItem; 00707 return TRUE; 00708 } 00709 else 00710 ERROR3("Trying to access element over the end of the array in CSampleData::GetAt"); 00711 } 00712 return FALSE; 00713 } 00714 00715 BOOL CSampleData::GetAtPos(double Index, CSampleItem* pItem) 00716 { 00717 ERROR2IF(pItem == NULL, FALSE, "Item pointer is NULL in CSampleData::GetAt"); 00718 00719 if (m_pSampleData != NULL) 00720 { 00721 //if (SetInternalRetrievalIndex(Index)) 00722 { 00723 //TRACEUSER( "Diccon", _T("Get At: ")); 00724 00725 UINT32 rounded = (UINT32) Index; 00726 00727 CSampleItem TheItem; 00728 if (GetItemAtInternalIndex((double) rounded, &TheItem)) 00729 *pItem = TheItem; 00730 return TRUE; 00731 } 00732 //else 00733 // ERROR3("Trying to access element over the end of the array in CSampleData::GetAt"); 00734 } 00735 return FALSE; 00736 } 00737 00738 00739 00740 00741 /******************************************************************************************** 00742 00743 > BOOL CSampleData::GetNext(CSampleItem* pItem) 00744 00745 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00746 Created: 31/5/2000 00747 Inputs: - 00748 Outputs: pItem - the tail item 00749 Returns: TRUE if successful, FALSE if we are at the end of the array or it doesn't exist 00750 Purpose: Increments the internal index, then retrieves the item at that index 00751 00752 Notes: It is recommended that you do a GetAt before you start doing GetNexts, otherwise 00753 I won't vouch for the position of the value of the internal index 00754 ********************************************************************************************/ 00755 00756 BOOL CSampleData::GetNext(CSampleItem* pItem) 00757 { 00758 BOOL Retval = FALSE; 00759 if (m_pSampleData != NULL) 00760 { 00761 //TRACEUSER( "Diccon", _T("Get Next: ")); 00762 if (IncrementInternalIndex(&m_RetrievalInternalIndex)) 00763 { 00764 // BODGE ALERT! if the retrieval index is -1 then this indicates that we 00765 // have reached the end of the array! However I am letting it pass on, 00766 // and have inserted more bodge code at GetItemAtInternalIndex to return 00767 // the last item. 00768 00769 // if (m_RetrievalInternalIndex == -1.0) 00770 // ERROR3("Invalid index in CSampleData::GetNext"); 00771 00772 { 00773 if (GetItemAtInternalIndex(m_RetrievalInternalIndex, pItem)) 00774 Retval = TRUE; 00775 } 00776 } 00777 else 00778 ERROR3("Unable to increment index in CSampleData::GetNext"); 00779 } 00780 00781 return Retval; 00782 } 00783 00784 /******************************************************************************************** 00785 00786 > BOOL CSampleData::GetPrev(CSampleItem* pItem) 00787 00788 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00789 Created: 31/5/2000 00790 Inputs: - 00791 Outputs: pItem - the previous item in the array 00792 Returns: TRUE if successful, FALSE if we are at the start of the array or it doesn't exist 00793 Purpose: Decrements our internal index and retrieves the item at that position 00794 00795 Notes: Really only works if the internal index has been set by a previous function such 00796 as GetAt, SetAt, etc. 00797 ********************************************************************************************/ 00798 00799 BOOL CSampleData::GetPrev(CSampleItem* pItem) 00800 { 00801 BOOL Retval = FALSE; 00802 if (m_pSampleData != NULL) 00803 { 00804 if (DecrementInternalIndex(&m_RetrievalInternalIndex)) 00805 { 00806 if (m_RetrievalInternalIndex != -1.0) 00807 { 00808 if (GetItemAtInternalIndex(m_RetrievalInternalIndex, pItem)) 00809 Retval = TRUE; 00810 } 00811 } 00812 else 00813 ERROR3("Unable to decrement index in CSampleData::GetPrev"); 00814 } 00815 return Retval; 00816 } 00817 00818 /******************************************************************************************** 00819 00820 > INT32 CSampleData::GetCount() 00821 00822 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00823 Created: 31/5/2000 00824 Inputs: - 00825 Outputs: - 00826 Returns: the number of items in the array, or -1 if the array does not exist 00827 Purpose: To find the number of items in the array 00828 00829 ********************************************************************************************/ 00830 00831 INT32 CSampleData::GetCount() 00832 { 00833 if (m_pSampleData != NULL) 00834 return (INT32)m_pSampleData->size(); 00835 00836 return -1; 00837 } 00838 00839 /******************************************************************************************** 00840 00841 > INT32 CSampleData::FreeExtra() 00842 00843 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00844 Created: 31/5/2000 00845 Inputs: - 00846 Outputs: - 00847 Returns: - 00848 Purpose: Asks the array to free any unused memory above its current upper bound. Recommneded 00849 that you call this if you do a big SetSize and don't use it all 00850 00851 ********************************************************************************************/ 00852 00853 void CSampleData::FreeExtra() 00854 { 00855 if (m_pSampleData != NULL) 00856 m_pSampleData->resize( (INT32)m_NumItems ); 00857 } 00858 00859 /******************************************************************************************** 00860 00861 > BOOL CSampleData::InsertNewData(UINT32 Index, CSampleData* pData) 00862 00863 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00864 Created: 31/5/2000 00865 Inputs: Index - the index to insert at 00866 pData - array of items to insert 00867 Outputs: - 00868 Returns: TRUE if successful 00869 Purpose: To insert pData into our data array at Index. This function does the shuffling 00870 of existing array elements in order to insert the new data 00871 00872 ********************************************************************************************/ 00873 00874 BOOL CSampleData::InsertNewData(UINT32 Index, CSampleData* pData) 00875 { 00876 ERROR2IF(pData == NULL, FALSE, "Attempting to insert null array in CSampleData::InsertNewData"); 00877 ERROR2IF(m_pSampleData == NULL, FALSE, "Member data array is NULL in CSampleData::InsertNewData"); 00878 00879 if (Index > m_pSampleData->size() - 1) 00880 { 00881 ERROR3("Attempting to insert beyond end of array in CSampleData::InsertNewData"); 00882 return FALSE; 00883 } 00884 00885 // find out how many elements we are inserting 00886 INT32 NumNewItems = (INT32)pData->GetNumItems(); 00887 if (NumNewItems <= 0) 00888 { 00889 ERROR3("Attempting to insert zero or fewer elements in BOOL CSampleData::InsertNewData"); 00890 return FALSE; 00891 } 00892 00893 // Set our sample rates to 1.0 so that we don't skip any elements 00894 m_CollectionSampleRate = 1.0; 00895 m_RetrievalSampleRate = 1.0; 00896 pData->SetRetrievalSampleRate(1.0); 00897 // work out how many elements we have to move 00898 size_t NumMoveItems = m_pSampleData->size() - 1 - Index; 00899 00900 // this keeps track of where we're moving from 00901 UINT32 MoveIndex = (UINT32)m_pSampleData->size() - 1; 00902 m_NumItems = m_pSampleData->size() + NumNewItems; 00903 // extend our array so we have room for the new data 00904 m_pSampleData->resize((INT32)m_NumItems); 00905 00906 // start at the tail and work down, shifting existing elements up to make room 00907 CSampleItem TheItem; 00908 BOOL KeepGoing = GetAt(MoveIndex, &TheItem); 00909 // TRACEUSER( "Diccon", _T("SHIFTING %d ITEMS UP FROM %d TO %d\n"), NumMoveItems, MoveIndex-NumMoveItems, MoveIndex-NumMoveItems + NumNewItems); 00910 while (NumMoveItems && KeepGoing) 00911 { 00912 // copy the item to its place further up in the array 00913 (*m_pSampleData)[MoveIndex + NumNewItems] = TheItem; 00914 // get the next item 00915 KeepGoing = GetPrev(&TheItem); 00916 MoveIndex--; 00917 NumMoveItems--; 00918 } 00919 // TRACEUSER( "Diccon", _T("FINISHED SHIFTING UP\n")); 00920 // now we can insert our new data at Index 00921 00922 // get the first item and set it, so we can use GetNext for each array 00923 KeepGoing = pData->GetAt(0, &TheItem); 00924 if (KeepGoing) 00925 SetAt(Index, TheItem); 00926 UINT32 Counter = 0; 00927 // TRACEUSER( "Diccon", _T("INSERTING NEW DATA\n")); 00928 while (NumNewItems && KeepGoing) 00929 { 00930 if (KeepGoing) KeepGoing = pData->GetNext(&TheItem); 00931 if (KeepGoing) SetNext(TheItem); 00932 //TRACEUSER( "Diccon", _T("Inserting item %d\n"), TheItem.m_Pressure); 00933 NumNewItems--; 00934 Counter++; 00935 } 00936 00937 //TRACEUSER( "Diccon", _T("Added %d items at index %d\n"), Counter, Index); 00938 // hopefully that should have done the trick! 00939 00940 return TRUE; 00941 } 00942 00943 /******************************************************************************************** 00944 00945 > BOOL CSampleData::RemoveData(UINT32 StartIndex, UINT32 EndIndex, SampleArray* pArray) 00946 00947 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 00948 Created: 31/5/2000 00949 Inputs: StartIndex - the index to start removing from 00950 EndIndex - the index to stop removing at 00951 Outputs: pArray (optional) - an array to store the removed elements in 00952 Returns: TRUE if successful 00953 Purpose: To remove all the items between StartIndex and EndIndex, and optionally record 00954 them in pArray 00955 00956 ********************************************************************************************/ 00957 00958 BOOL CSampleData::RemoveData(UINT32 StartIndex, UINT32 EndIndex, SampleArray* pArray) 00959 { 00960 // do some checks 00961 ERROR2IF(m_pSampleData == NULL, FALSE, "Attempting to remove from an array that doesn't exist in CSampleData::RemoveData"); 00962 ERROR2IF(EndIndex <= StartIndex, FALSE, "Invalid indexes in CSampleData::RemoveData"); 00963 00964 UINT32 UpperBound = (UINT32)m_pSampleData->size() - 1; 00965 if (StartIndex > UpperBound || EndIndex > UpperBound) 00966 { 00967 ERROR3("Attempting to remove items beyond the bounds of the array in CSampleData::RemoveData"); 00968 return FALSE; 00969 } 00970 // Set our samples rate to 1.0 so that we don't skip any elements 00971 m_CollectionSampleRate = 1.0; 00972 m_RetrievalSampleRate = 1.0; 00973 00974 // find out how many we're dealing with 00975 UINT32 NumRemoveItems = EndIndex - StartIndex; 00976 00977 // TRACEUSER( "Diccon", _T("COPYING ITEMS TO BE REMOVED\n")); 00978 // first copy the removed items to the new array (if relevant) 00979 if (pArray != NULL) 00980 { 00981 pArray->resize( NumRemoveItems ); 00982 CSampleItem TheItem; 00983 for (UINT32 i = 0; i < NumRemoveItems; i++) 00984 { 00985 TheItem = (*m_pSampleData)[i + StartIndex]; 00986 (*pArray)[i] = TheItem; 00987 // TRACEUSER( "Diccon", _T("Removing data %d\n"), TheItem.m_Pressure); 00988 } 00989 } 00990 00991 // now copy all elements beyond EndIndex back to StartIndex 00992 UINT32 NumMoveItems = UpperBound - EndIndex; 00993 UINT32 NumItemsMoved = 0; 00994 CSampleItem TheItem; 00995 // EndIndex +1 ?? 00996 // UINT32 Index = StartIndex; 00997 // TRACEUSER( "Diccon", _T("SHIFTING ITEMS DOWN FROM %d TO %d\n"), EndIndex, Index); 00998 // TRACEUSER( "Diccon", _T("Upper bound = %d\n"), UpperBound); 00999 BOOL ok = GetAt(EndIndex, &TheItem); 01000 INT32 RemoveCount = NumRemoveItems; 01001 while ((NumItemsMoved <= NumMoveItems) && ok) 01002 { 01003 (*m_pSampleData)[StartIndex++] = TheItem; 01004 ok = GetNext(&TheItem); 01005 NumItemsMoved++; 01006 if (RemoveCount > 0) 01007 { 01008 RemoveCount--; 01009 m_NumItems--; // decrement the number of items 01010 } 01011 } 01012 01013 // TRACEUSER( "Diccon", _T("Removed %d items\n"), EndIndex - Index); 01014 // TRACEUSER( "Diccon", _T("Moved %d items from index %d to index %d\n"), NumItemsMoved, EndIndex, Index); 01015 // shrink the array to the new size 01016 m_pSampleData->resize( m_NumItems ); 01017 01018 return TRUE; 01019 } 01020 01021 01022 /******************************************************************************************** 01023 01024 > BOOL CSampleData::SetInternalCollectionIndex(UINT32 IndexRequested) 01025 01026 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01027 Created: 31/5/2000 01028 Inputs: IndexRequested - the requested index to set the array pointer to 01029 Outputs: - 01030 Returns: TRUE, unless index converts to an internal index that is out of bounds 01031 Purpose: Sets our collection internal array index to the position corresponding to the 01032 requested index 01033 01034 ********************************************************************************************/ 01035 01036 BOOL CSampleData::SetInternalCollectionIndex(UINT32 Index) 01037 { 01038 ERROR2IF(m_pSampleData == NULL, FALSE, "Sample data is null in CSampleData::SetInternalIndex"); 01039 01040 BOOL Retval = FALSE; 01041 01042 double TempIndex = m_CollectionSampleRate * Index; 01043 if (TempIndex <= (double)m_pSampleData->size() - 1 && TempIndex >= 0) 01044 { 01045 m_CollectionInternalIndex = TempIndex; 01046 Retval = TRUE; 01047 } 01048 else 01049 ERROR3("Attempting to set internal index beyond the end of the array in CSampleData::SetInternalIndex"); 01050 01051 return Retval; 01052 } 01053 01054 01055 /******************************************************************************************** 01056 01057 > BOOL CSampleData::SetInternalRetrievalIndex(UINT32 IndexRequested) 01058 01059 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01060 Created: 31/5/2000 01061 Inputs: IndexRequested - the requested index to set the array pointer to 01062 Outputs: - 01063 Returns: TRUE, unless index converts to an internal index that is out of bounds 01064 Purpose: Sets our Retrieval internal array index to the position corresponding to the 01065 requested index 01066 01067 ********************************************************************************************/ 01068 01069 BOOL CSampleData::SetInternalRetrievalIndex(UINT32 Index) 01070 { 01071 ERROR2IF(m_pSampleData == NULL, FALSE, "Sample data is null in CSampleData::SetInternalIndex"); 01072 01073 BOOL Retval = FALSE; 01074 01075 double TempIndex = m_RetrievalSampleRate * Index; 01076 if (TempIndex <= (double)m_pSampleData->size() - 1) 01077 { 01078 m_RetrievalInternalIndex = TempIndex; 01079 Retval = TRUE; 01080 } 01081 else 01082 ERROR3("Attempting to set internal index beyond the end of the array in CSampleData::SetInternalIndex"); 01083 01084 return Retval; 01085 } 01086 01087 01088 /******************************************************************************************** 01089 01090 > BOOL CSampleData::IncrementInternalIndex(double* pCurrentIndex) 01091 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01092 Created: 31/5/2000 01093 Inputs: pCurrentIndex - the index to be incremented, this should really only be either 01094 the collection index or the retrieval index 01095 Outputs: - 01096 Returns: TRUE, unless something goes wrong 01097 Purpose: Increments our internal index counter, unless we have reached 01098 the end of the array in which case we set the counter to -1 01099 01100 ********************************************************************************************/ 01101 01102 BOOL CSampleData::IncrementInternalIndex(double* pCurrentIndex) 01103 { 01104 // if we've already overrun then don't go any further 01105 if (*pCurrentIndex == -1) 01106 return TRUE; 01107 01108 // not allowed to use indexes that aren't one of our members, also 01109 // find out which sample rate to use here 01110 double SampleRate = 1.0; 01111 if (pCurrentIndex == &m_CollectionInternalIndex) 01112 { 01113 SampleRate = m_CollectionSampleRate; 01114 } 01115 else if (pCurrentIndex == &m_RetrievalInternalIndex) 01116 { 01117 SampleRate = m_RetrievalSampleRate; 01118 } 01119 else 01120 { 01121 ERROR3("Attempting to use non-member index in CSampleData::IncrementInternalIndex"); 01122 return FALSE; 01123 } 01124 01125 // we need to have valid sample data 01126 ERROR2IF(m_pSampleData == NULL, FALSE, "Sample data is null in CSampleData::IncrementInternalIndex"); 01127 01128 double TestIndex = *pCurrentIndex + SampleRate; 01129 // TRACEUSER( "Diccon", _T(" Internal index = %f"), TestIndex); 01130 // TRACEUSER( "Diccon", _T(", Upper bound = %f\n"), (double)(m_pSampleData->size() - 1)); 01131 if (TestIndex <= (double)(m_pSampleData->size() - 1)) 01132 { 01133 *pCurrentIndex += SampleRate; 01134 } 01135 else 01136 { 01137 01138 // TRACEUSER( "Diccon", _T("END OF ARRAY, Test index = %f, Num items = %d\n"), TestIndex, m_NumItems); 01139 *pCurrentIndex = -1; 01140 01141 } 01142 01143 01144 return TRUE; 01145 } 01146 01147 /******************************************************************************************** 01148 01149 > BOOL CSampleData::DecrementInternalIndex(double* pCurrentIndex) 01150 01151 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01152 Created: 31/5/2000 01153 Inputs: pCurrentIndex - the index to be decremented, this should really only be either 01154 the collection index or the retrieval index 01155 Outputs: - 01156 Returns: TRUE, unless something went wrong 01157 Purpose: Decrements our internal array pointer and index counter, unless we have reached 01158 the start of the array in which case we set it to -1. 01159 ********************************************************************************************/ 01160 01161 BOOL CSampleData::DecrementInternalIndex(double* pCurrentIndex) 01162 { 01163 // not allowed to use indexes that aren't one of our members, also 01164 // find out which sample rate to use here 01165 double SampleRate = 1.0; 01166 if (pCurrentIndex == &m_CollectionInternalIndex) 01167 { 01168 SampleRate = m_CollectionSampleRate; 01169 } 01170 else if (pCurrentIndex == &m_RetrievalInternalIndex) 01171 { 01172 SampleRate = m_RetrievalSampleRate; 01173 } 01174 else 01175 { 01176 ERROR3("Attempting to use non-member index in CSampleData::DecrementInternalIndex"); 01177 return FALSE; 01178 } 01179 01180 // we need to have valid sample data 01181 ERROR2IF(m_pSampleData == NULL, FALSE, "Sample data is null in CSampleData::DecrementInternalIndex"); 01182 01183 double TestIndex = *pCurrentIndex - SampleRate; 01184 if (TestIndex > 0) 01185 { 01186 *pCurrentIndex -= SampleRate; 01187 } 01188 else 01189 { 01190 *pCurrentIndex = -1; 01191 } 01192 return TRUE; 01193 } 01194 01195 01196 /******************************************************************************************** 01197 01198 > BOOL CSampleData::GetItemAtInternalIndex(double Index, CSampleItem* pItem) 01199 01200 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01201 Created: 31/5/2000 01202 Inputs: Index - the index to get the value from. Note that this does not have to be 01203 an integer, should really be the collection or retrieval index only 01204 Outputs: pointer to item retrieved 01205 Returns: TRUE if all went well, FALSE if we don't have an array or the index is invalid 01206 Purpose: Retrieves the item in the array indicated by the current internal index. Note 01207 that it is possible that this index may not be an integer in which case this 01208 function will generate a new CSampleItem by interpolation 01209 01210 ********************************************************************************************/ 01211 01212 BOOL CSampleData::GetItemAtInternalIndex(double Index, CSampleItem* pItem) 01213 { 01214 // no reason why you shouldn't be using this function on values other than our member 01215 // indexes but that is not the intended purpose of this fn. hence the ERROR3 01216 //if (Index != m_CollectionInternalIndex && Index != m_RetrievalInternalIndex) 01217 // ERROR3("Attempting to use non-member index in CSampleData::GetItemAtInternalIndex"); 01218 01219 ERROR2IF(m_pSampleData == NULL, FALSE, "Sample data is null in CSampleData::GetItemAtInternalIndex"); 01220 01221 BOOL Retval = FALSE; 01222 //TRACEUSER( "Diccon", _T("Retrieving item at %f\n"), Index); 01223 01224 double UpperBound = (double)m_pSampleData->size() - 1; 01225 01226 // If our index is -1 then we have run off the end of the array, so return the last item 01227 if (Index == -1) 01228 Index = UpperBound; 01229 01230 if (Index <= UpperBound) 01231 { 01232 size_t LowIndex = (UINT32)Index; 01233 if (LowIndex > m_NumItems) 01234 //ERROR3("Attempting to access data that has not been collected in CSampleData::GetItemAtInternalIndex"); 01235 LowIndex = m_NumItems; //bodge alert! 01236 01237 UINT32 HighIndex = (UINT32)Index+1; 01238 if (HighIndex < m_NumItems) 01239 { 01240 double Proportion = Index - (double)LowIndex; 01241 CSampleItem LowItem = (*m_pSampleData)[LowIndex]; 01242 CSampleItem HighItem = (*m_pSampleData)[HighIndex]; 01243 CSampleItem NewItem = LowItem.InterpolateItems(HighItem, (1-Proportion)); 01244 //TRACEUSER( "Diccon", _T("Lo = %d, Hi = %d, Prop =%f, Pressure = %d\n"), LowIndex, HighIndex, Proportion, NewItem.m_Pressure); 01245 *pItem = NewItem; 01246 } 01247 else 01248 *pItem = (*m_pSampleData)[LowIndex]; 01249 01250 Retval = TRUE; 01251 } 01252 else 01253 ERROR3("Internal index is over the end of the array in CSampleData::GetItemAtInternalIndex"); 01254 01255 return Retval; 01256 } 01257 01258 /*------------------------------------------------------------------------------------------ 01259 -----------------------------------Other functions------------------------------------------ 01260 -------------------------------------------------------------------------------------------*/ 01261 01262 /******************************************************************************************** 01263 01264 > BOOL CSampleData::SetCollectionSampleRate(UINT32 Rate) 01265 01266 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01267 Created: 31/5/2000 01268 Inputs: Rate - the sample rate to use 01269 Outputs: - 01270 Returns: TRUE if Rate is within the set bounds 01271 Purpose: Sets the sample rate to use for collecting data. Note that for current purposes 01272 this is only allowed to be 1. So you probably won't be using this function 01273 very often. 01274 ********************************************************************************************/ 01275 01276 BOOL CSampleData::SetCollectionSampleRate(double Rate) 01277 { 01278 if (Rate < MIN_COLLECTION_SAMPLE_RATE || Rate > MAX_COLLECTION_SAMPLE_RATE) 01279 { 01280 ERROR3("Attempting to set invalid sample rate in CSampleData::SetCollectionSampleRate"); 01281 return FALSE; 01282 } 01283 01284 m_CollectionSampleRate = Rate; 01285 01286 return TRUE; 01287 } 01288 01289 /******************************************************************************************** 01290 01291 > double CSampleData::GetCollectionSampleRate() 01292 01293 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01294 Created: 31/5/2000 01295 Inputs: - 01296 Outputs: - 01297 Returns: the current collection sample rate 01298 Purpose: as above 01299 01300 ********************************************************************************************/ 01301 01302 double CSampleData::GetCollectionSampleRate() 01303 { 01304 return m_CollectionSampleRate; 01305 } 01306 01307 /******************************************************************************************** 01308 01309 > BOOL CSampleData::SetRetrievalSampleRate(UINT32 Rate) 01310 01311 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01312 Created: 31/5/2000 01313 Inputs: Rate - the sample rate to use 01314 Outputs: - 01315 Returns: TRUE if Rate is within the set bounds 01316 Purpose: Sets the sample rate to use for retrieving data, 01317 ********************************************************************************************/ 01318 01319 BOOL CSampleData::SetRetrievalSampleRate(double Rate) 01320 { 01321 // CGS: because of the way that I now use this function, its NOT fair to do the following .... 01322 01323 if (Rate < MIN_RETRIEVAL_SAMPLE_RATE || Rate > MAX_RETRIEVAL_SAMPLE_RATE) 01324 { 01325 TRACE( _T("Sample rate passed to CSampleData::SetRetrievalSampleRate was oustide of range!") ); 01326 //ERROR3("Attempting to set invalid sample rate in CSampleData::SetRetrievalSampleRate"); 01327 //return FALSE; 01328 } 01329 01330 if (Rate < MIN_RETRIEVAL_SAMPLE_RATE) Rate = MIN_RETRIEVAL_SAMPLE_RATE; 01331 if (Rate > MAX_RETRIEVAL_SAMPLE_RATE) Rate = MAX_RETRIEVAL_SAMPLE_RATE; 01332 01333 m_RetrievalSampleRate = Rate; 01334 01335 return TRUE; 01336 } 01337 01338 /******************************************************************************************** 01339 01340 > double CSampleData::GetRetrievalSampleRate() 01341 01342 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01343 Created: 31/5/2000 01344 Inputs: - 01345 Outputs: - 01346 Returns: the current Retrieval sample rate 01347 Purpose: as above 01348 01349 ********************************************************************************************/ 01350 01351 double CSampleData::GetRetrievalSampleRate() 01352 { 01353 return m_RetrievalSampleRate; 01354 } 01355 01356 /******************************************************************************************** 01357 01358 > void CSampleData::SetMaxPressure(UINT32 Max) 01359 01360 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01361 Created: 31/5/2000 01362 Inputs: Max - the maximum pressure value allowed by the current pressure device 01363 Outputs: - 01364 Returns: - 01365 Purpose: To set our max pressure member. Do this by querying the WinTab device BEFORE 01366 you start collecting data. 01367 01368 ********************************************************************************************/ 01369 01370 void CSampleData::SetMaxPressure(UINT32 Max) 01371 { 01372 m_MaxPressure = Max; 01373 01374 // +1 because values go from 0 -> MaxVal whereas we really want the number of values 01375 m_ScalePressure = (double)(MAXPRESSURE+1) / (Max+1); 01376 01377 } 01378 01379 /******************************************************************************************** 01380 01381 > UINT32 CSampleData::GetMaxPressure() 01382 01383 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01384 Created: 31/5/2000 01385 Inputs: - 01386 Outputs: - 01387 Returns: the maximum pressure value allowed by the device sending the pressure data 01388 Purpose: as above 01389 01390 ********************************************************************************************/ 01391 01392 UINT32 CSampleData::GetMaxPressure() 01393 { 01394 return m_MaxPressure; 01395 } 01396 01397 /******************************************************************************************** 01398 01399 > void CSampleData::SetSampleArray(SampleArray* pArray) 01400 01401 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01402 Created: 31/5/2000 01403 Inputs: pArray - the array to set as a data member 01404 Outputs: - 01405 Returns: - 01406 Purpose: sets the given array to use as our sample data 01407 01408 ********************************************************************************************/ 01409 01410 void CSampleData::SetSampleArray(SampleArray* pArray) 01411 { 01412 // if we've already got one then delete it 01413 if (m_pSampleData != NULL) 01414 { 01415 m_pSampleData->clear(); 01416 delete m_pSampleData; 01417 m_pSampleData = NULL; 01418 } 01419 m_pSampleData = pArray; 01420 } 01421 01422 /******************************************************************************************** 01423 01424 01425 > BOOL CSampleData::ReverseData() 01426 01427 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01428 Created: 13/12/99 01429 Inputs: - 01430 Returns: TRUE if successful, FALSE if we didn't get the memory 01431 Purpose: Reverses the items in the data array, or rather just copies them into a new one 01432 ********************************************************************************************/ 01433 01434 BOOL CSampleData::ReverseData() 01435 { 01436 if (m_pSampleData == NULL) 01437 return TRUE; //EASY 01438 01439 size_t ArraySize = m_NumItems; 01440 01441 if (ArraySize == 0) 01442 return TRUE; // also easy 01443 01444 // make a new array 01445 SampleArray* pNewArray = new SampleArray; 01446 if (pNewArray == NULL) 01447 return FALSE; 01448 01449 pNewArray->resize( ArraySize ); 01450 01451 size_t UpperBound = ArraySize-1; 01452 CSampleItem TheItem; 01453 // BOOL ok = TRUE; 01454 // take the item at the start of our member array and set it at the end of the new array 01455 for (UINT32 Counter = 0; Counter < (UINT32)ArraySize ; Counter++) 01456 { 01457 TheItem = (*m_pSampleData)[Counter]; 01458 (*pNewArray)[UpperBound - Counter] = TheItem; 01459 } 01460 // swap the pointers 01461 SampleArray* pTemp = m_pSampleData; 01462 m_pSampleData = pNewArray; 01463 01464 // clear out the original 01465 pTemp->clear(); 01466 delete pTemp; 01467 01468 return TRUE; 01469 } 01470 01471 /******************************************************************************************** 01472 01473 01474 > void CSampleData::FinishSampling() 01475 01476 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01477 Created: 13/12/99 01478 Inputs: - 01479 Returns: - 01480 Purpose: Tells the object that sampling has finished. As a security precaution we will 01481 add an extra 10 * m_RetrievalSampleRates worth of entries. 01482 The real reason for this hack is that once the path is entered it is then smoothed, 01483 which causes the path length to increase. Since we never sampled over this increased 01484 length we need to kind of pretend that we did. 01485 ********************************************************************************************/ 01486 01487 void CSampleData::FinishSampling() 01488 { 01489 if (m_pSampleData != NULL) 01490 { 01491 // find out how many items to insert 01492 UINT32 NumExtraItems = (UINT32)(m_RetrievalSampleRate * 10); 01493 01494 // get the last item we inserted 01495 UINT32 InsertIndex = (UINT32)m_CollectionInternalIndex; 01496 CSampleItem TheItem = (*m_pSampleData)[InsertIndex]; 01497 01498 // make sure the array is big enough 01499 UINT32 CurrentSize = (INT32)m_pSampleData->size(); 01500 if (CurrentSize < InsertIndex+NumExtraItems) 01501 { 01502 m_pSampleData->resize( CurrentSize + NumExtraItems ); 01503 } 01504 01505 01506 01507 for (UINT32 i = 1; i <= NumExtraItems; i++) 01508 { 01509 (*m_pSampleData)[InsertIndex + i] = TheItem; 01510 m_NumItems++; 01511 } 01512 } 01513 } 01514 /******************************************************************************************** 01515 01516 01517 > void CSampleData::SetNumItemsFromArraySize() 01518 01519 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01520 Created: 13/12/99 01521 Inputs: - 01522 Returns: - 01523 Purpose: Sets the num items member from the size of the array. Note that you should 01524 never really use this unless you are certain that a) your current m_NumItems 01525 is incorrect and b)You are certain that your array contains nothing but valid 01526 data. 01527 An example of when you should use this is if you decide to set the array from 01528 out side, rather than collect it through sampling. And you really shouldn't 01529 be doing that either. 01530 ********************************************************************************************/ 01531 01532 void CSampleData::SetNumItemsFromArraySize() 01533 { 01534 if (m_pSampleData != NULL) 01535 m_NumItems = (UINT32)m_pSampleData->size(); 01536 else 01537 m_NumItems = 0; 01538 } 01539 01540 /******************************************************************************************** 01541 01542 01543 > BOOL CSampleData::ClipArray(UINT32 Size) 01544 01545 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01546 Created: 13/12/99 01547 Inputs: Size - the desired array size 01548 Returns: TRUE unless Size is bigger than the array we have 01549 Purpose: Clips the array to be the desired size, be careful with this as you will lose 01550 all data beyond the Size'th index. 01551 ********************************************************************************************/ 01552 01553 BOOL CSampleData::ClipArray(size_t Size) 01554 { 01555 ERROR2IF(m_pSampleData == NULL, FALSE, "Sample data is NULL in CSampleData::ClipArray"); 01556 ERROR2IF(Size > (UINT32)m_pSampleData->size(), FALSE, "Attempting to clip over the end of the array in CSampleData::ClipArray"); 01557 01558 m_pSampleData->resize( Size ); 01559 if (m_NumItems > Size) 01560 m_NumItems = Size; 01561 01562 return TRUE; 01563 } 01564 01565 01566 /******************************************************************************************** 01567 01568 > BOOL CSampleData::ReSampleArray(SampleArray** ppArray, UINT32 NewNumItems) 01569 01570 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01571 Created: 12/6/2000 01572 Inputs: pArray - the array to be resampled 01573 NewNumItems - the number of items we want to end up with in the array 01574 Returns: TRUE if successful, FALSE if something went wrong 01575 Purpose: Resamples the data in the sample array so that we end up with NewNumItems in 01576 the section required. We will do this by selecting some resampling points in 01577 the original array, maintain these points at the same proportional position 01578 and interpolate to get the new points. 01579 01580 Notes: Because, in reality most of our 'sampled' points are actually interpolated 01581 from a smaller number of data points collected I feel that we don't actually 01582 lose much accuracy if we just take one in every four points as a control point. 01583 01584 ********************************************************************************************/ 01585 01586 BOOL CSampleData::ReSampleArray(SampleArray** ppArray, UINT32 NewNumItems) 01587 { 01588 SampleArray* pArray = *ppArray; 01589 // check our input conditions 01590 ERROR2IF(pArray == NULL, FALSE, "Sample array is NULL in CSampleData::ReSampleData"); 01591 01592 01593 if (NewNumItems == 0) // well this is easy 01594 { 01595 pArray->clear(); 01596 return TRUE; 01597 } 01598 01599 // allocate a new array to put the resampled data in 01600 SampleArray* pNewArray = new SampleArray; 01601 if (pNewArray == NULL) 01602 return FALSE; 01603 pNewArray->resize( NewNumItems ); 01604 01605 // how many items per control item 01606 UINT32 ItemsPerControl = 4; // magic number alert!! 01607 01608 // Insert the control points into the new array 01609 if (!InsertControlPoints(ItemsPerControl, pArray, pNewArray)) 01610 { 01611 pNewArray->clear(); 01612 delete pNewArray; 01613 return FALSE; 01614 } 01615 01616 // proceed through the new array interpolating between the control points. 01617 // We will be able to tell the control points because their coordinates will be non-zero 01618 01619 UINT32 ControlIndex1 = 0; // first point is a control point 01620 UINT32 ControlIndex2 = 0; 01621 CSampleItem TheItem; 01622 01623 UINT32 Index = 0; 01624 01625 while (Index < NewNumItems) 01626 { 01627 TheItem = (*pNewArray)[Index]; 01628 if (TheItem.m_Coord.x != 0 && TheItem.m_Coord.y != 0) // got another control 01629 { 01630 ControlIndex2 = Index; 01631 if (Index != 0) 01632 InterpolateItems(ControlIndex1, ControlIndex2, pNewArray); 01633 ControlIndex1 = ControlIndex2; // current control becomes first control 01634 } 01635 Index++; 01636 } 01637 01638 // now we have to destroy the original array and swap the pointers 01639 delete pArray; 01640 *ppArray = pNewArray; 01641 01642 return TRUE; 01643 } 01644 01645 01646 /******************************************************************************************** 01647 01648 > BOOL CSampleData::InsertControlPoints(UINT32 Frequency, SampleArray* pOriginal, 01649 SampleArray* pNew) 01650 01651 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01652 Created: 12/6/2000 01653 Inputs: Frequency - the number of indexes per control point. i.e. 4 = a control point 01654 every 4th index. 01655 pOriginal - the original array 01656 pNew - the new array, this MUST be allocated AND sized 01657 Returns: TRUE if successful, FALSE if something went wrong 01658 Purpose: As part of the ReSampleArray process this function takes the case where we need 01659 to increase the number of control points. It therefore proceeds through the original 01660 array copying control points over at the same proportional position as they were in 01661 the original array. 01662 01663 01664 ********************************************************************************************/ 01665 01666 BOOL CSampleData::InsertControlPoints(UINT32 Frequency, SampleArray* pOriginal, SampleArray* pNew) 01667 { 01668 ERROR2IF(pOriginal == NULL, FALSE, "Original array is NULL in CSampleData::InsertControlPoints"); 01669 ERROR2IF(pNew == NULL, FALSE, "New array is NULL in CSampleData::InsertControlPoints"); 01670 01671 double NumOrigItems = (double)pOriginal->size(); 01672 double NumNewItems = (double)pNew->size(); 01673 01674 INT32 OrigIndex = 0; 01675 double dOrigIndex = 0; 01676 INT32 NewIndex = 0; 01677 01678 CSampleItem TheItem; 01679 double OrigProportion; 01680 while (OrigIndex < NumOrigItems) 01681 { 01682 TheItem = (*pOriginal)[OrigIndex]; 01683 OrigProportion = dOrigIndex / NumOrigItems; 01684 NewIndex = (INT32)(OrigProportion * NumNewItems); 01685 if (NewIndex < NumNewItems) 01686 (*pNew)[NewIndex] = TheItem; 01687 else 01688 ERROR3("Attempting to set over the end of the new array in CSampleData::InsertControlPoints"); 01689 OrigIndex += Frequency; 01690 dOrigIndex += Frequency; 01691 } 01692 return TRUE; 01693 } 01694 01695 /******************************************************************************************** 01696 01697 > BOOL CSampleData::GetArraySection(UINT32 StartIndex, UINT32 EndIndex, SampleArray* pSection) 01698 01699 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01700 Created: 12/6/2000 01701 Inputs: StartIndex - the internal index at which to start the resampling 01702 EndIndex - the internal index to finish the resampling 01703 pSection - a to an allocated sample array 01704 Outputs: Allocatest the array and fills it with data from the section 01705 Returns: TRUE if successful, FALSE if something went wrong 01706 Purpose: To copy the data from the section specified into a new array that we will 01707 create. 01708 01709 Errors: if StartIndex or EndIndex are invalid, or if we don't have a sample array 01710 01711 ********************************************************************************************/ 01712 01713 BOOL CSampleData::GetArraySection(UINT32 StartIndex, UINT32 EndIndex, SampleArray* pSection) 01714 { 01715 // check our input conditions 01716 ERROR2IF(pSection == NULL, FALSE, "Sample array is NULL in CSampleData::GetArraySection"); 01717 if (EndIndex <= StartIndex || EndIndex > m_NumItems) 01718 { 01719 ERROR3("Invalid indexes in CSampleData::GetArraySection"); 01720 return FALSE; 01721 } 01722 01723 UINT32 NumItems = EndIndex - StartIndex; 01724 pSection->resize(NumItems); 01725 01726 // we want to make sure we retrieve all the items 01727 m_RetrievalSampleRate = 1.0; 01728 01729 // We have to do the first one manually, due to my rather clumsy implementation 01730 CSampleItem TheItem; 01731 BOOL ok = GetAt(StartIndex, &TheItem); 01732 if (ok) 01733 (*pSection)[0] = TheItem; 01734 else 01735 ERROR3("Failed to retrieve first item in CSampleData::GetArraySection"); 01736 01737 UINT32 Counter = 1; 01738 while (ok && (Counter < NumItems)) 01739 { 01740 ok = GetNext(&TheItem); 01741 (*pSection)[Counter] = TheItem; 01742 Counter++; 01743 } 01744 01745 // Did we copy the right number of items? 01746 if (Counter != NumItems) 01747 { 01748 ERROR3("Error copying data in CSampleData::GetArraySection"); 01749 ok = FALSE; 01750 } 01751 else 01752 ok = TRUE; 01753 return ok; 01754 } 01755 01756 01757 /******************************************************************************************** 01758 01759 01760 > BOOL CSampleData::InterpolateItems(UINT32 StartIndex, UINT32 EndIndex, SampleArray* pArray) 01761 01762 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01763 Created: 13/6/2000 01764 Inputs: StartIndex, EndIndex - the indexes to interpolate between 01765 pArray - the array to do the interpolatin' on 01766 Outputs: the interpolated array 01767 Returns: TRUE unless the indexes are wack 01768 Purpose: Interpolates between the two indexes in the array, creating intermediate items 01769 and inserting them 01770 01771 ********************************************************************************************/ 01772 01773 BOOL CSampleData::InterpolateItems(UINT32 StartIndex, UINT32 EndIndex, SampleArray* pArray) 01774 { 01775 ERROR2IF(pArray == NULL, FALSE, "Sample array is NULL in CSampleData::InterpolateItems"); 01776 size_t MaxIndex = pArray->size() - 1; 01777 01778 if (EndIndex <= StartIndex || EndIndex > MaxIndex) 01779 { 01780 ERROR3("Invalid indexes in CSampleData::InterpolateItems"); 01781 return FALSE; 01782 } 01783 // get the two items to interpolate between 01784 CSampleItem FirstItem = (*pArray)[StartIndex]; 01785 CSampleItem LastItem = (*pArray)[EndIndex]; 01786 01787 // get the proportional changes for each step 01788 UINT32 NumItems = EndIndex - StartIndex; 01789 double ItemProportion = 1 / (double)NumItems; 01790 01791 MILLIPOINT XVal = (INT32)((double)(LastItem.m_Coord.x - FirstItem.m_Coord.x) * ItemProportion); 01792 MILLIPOINT YVal = (INT32)((double)(LastItem.m_Coord.y - FirstItem.m_Coord.y) * ItemProportion); 01793 INT32 PressVal = (INT32) (((double)(LastItem.m_Pressure - FirstItem.m_Pressure) * ItemProportion)); 01794 01795 UINT32 Index = StartIndex + 1; 01796 CSampleItem NewItem = FirstItem; 01797 while (Index < EndIndex) 01798 { 01799 NewItem.m_Coord.x += XVal; 01800 NewItem.m_Coord.y += YVal; 01801 NewItem.m_Pressure += PressVal; 01802 (*pArray)[Index] = NewItem; 01803 Index++; 01804 } 01805 return TRUE; 01806 } 01807 01808 /******************************************************************************************** 01809 01810 01811 > BOOL CSampleData::WriteNative(CXaraFileRecord* pRecord) 01812 01813 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01814 Created: 13/12/99 01815 Inputs: pRecord - the record to write to 01816 Returns: TRUE if the Node has written out a record to the filter 01817 Purpose: Writes out the data contained in this SampleData to a record 01818 01819 ********************************************************************************************/ 01820 01821 BOOL CSampleData::WriteNative(CXaraFileRecord* pRecord) 01822 { 01823 ERROR2IF(pRecord == NULL, FALSE, "Record is NULL in CSampleData::WriteNative"); 01824 01825 BOOL ok = TRUE; 01826 ok = pRecord->WriteINT32((INT32)m_NumItems); 01827 01828 if (m_pSampleData != NULL) 01829 { 01830 CSampleItem TheItem; 01831 01832 SetRetrievalSampleRate(1.0); // as we want 01833 BOOL KeepWriting = GetAt(0, &TheItem); // get the first itemto save out every item 01834 01835 01836 UINT32 Counter = 0; 01837 // note that GetNext returns FALSE it just means we've reached the end, not an error 01838 while (ok && Counter <= m_NumItems && KeepWriting) 01839 { 01840 if (ok) ok = TheItem.WriteNative(pRecord); 01841 KeepWriting = GetNext(&TheItem); 01842 Counter++; 01843 } 01844 } 01845 return ok; 01846 } 01847 01848 /*------------------------------------------------------------------------------------------- 01849 ------------------------------CPressureSampler implementation------------------------------------- 01850 --------------------------------------------------------------------------------------------- 01851 */ 01852 01853 /******************************************************************************************** 01854 01855 > CDistanceSampler::CDistanceSampler() 01856 01857 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01858 Created: 31/5/2000 01859 Inputs: - 01860 Outputs: - 01861 Returns: this object 01862 Purpose: default constructor 01863 01864 Notes: 01865 ********************************************************************************************/ 01866 01867 CDistanceSampler::CDistanceSampler() 01868 { 01869 m_SampleDistance = MIN_BRUSH_SPACING; 01870 m_DistanceSinceLastSample = -1; 01871 m_DistanceSoFar = 0; 01872 m_TotalDistance = 0; 01873 m_ItemsInserted = 0; 01874 m_DistanceSinceLastData = 0; 01875 m_ItemRemainder = 0.0; 01876 } 01877 01878 /******************************************************************************************** 01879 01880 > CDistanceSampler::~CDistanceSampler() 01881 01882 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01883 Created: 31/5/2000 01884 Inputs: - 01885 Outputs: - 01886 Returns: this object 01887 Purpose: destructor 01888 01889 Notes: 01890 ********************************************************************************************/ 01891 01892 CDistanceSampler::~CDistanceSampler() 01893 { 01894 01895 } 01896 01897 /******************************************************************************************** 01898 01899 > BOOL CDistanceSampler::SetSampleDistance(MILLIPOINT Distance) 01900 01901 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01902 Created: 31/5/2000 01903 Inputs: Distance - the distance to sample at 01904 Outputs: - 01905 Returns: TRUE, unless Distance is out of bounds 01906 Purpose: Sets the sample distance, I can't see why you would wish to sample at anything 01907 other than MIN_BRUSH_SPACING, but each to their own 01908 01909 Notes: 01910 ********************************************************************************************/ 01911 01912 BOOL CDistanceSampler::SetSampleDistance(MILLIPOINT Distance) 01913 { 01914 if (Distance < MIN_BRUSH_SPACING || Distance > MAX_BRUSH_SPACING) 01915 { 01916 ERROR3("Invalid distaance in CDistanceSampler::SetSampleDistance"); 01917 return FALSE; 01918 } 01919 m_SampleDistance = Distance; 01920 01921 return TRUE; 01922 } 01923 01924 /******************************************************************************************** 01925 01926 > BOOL CDistanceSampler::SetSampleDistance(MILLIPOINT Distance) 01927 01928 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01929 Created: 31/5/2000 01930 Inputs: - 01931 Outputs: - 01932 Returns: our sample distance 01933 Purpose: access fn. 01934 01935 Notes: 01936 ********************************************************************************************/ 01937 01938 MILLIPOINT CDistanceSampler::GetSampleDistance() 01939 { 01940 return m_SampleDistance; 01941 } 01942 01943 /******************************************************************************************** 01944 01945 > BOOL CDistanceSampler::CollectData(DocCoord Coord, UINT32 Pressure) 01946 01947 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 01948 Created: 31/5/2000 01949 Inputs: Coord - the current coordinate 01950 Pressure - the current pressure 01951 Outputs: - 01952 Returns: TRUE if successful, FALSE if something went wrong 01953 Purpose: This function is in charge of doing the actual sampling of data 01954 01955 Notes: 01956 ********************************************************************************************/ 01957 01958 BOOL CDistanceSampler::CollectData(DocCoord Coord, UINT32 Pressure) 01959 { 01960 // first up check that we have set the max pressure value 01961 ERROR2IF(m_MaxPressure == 0, FALSE, "You're supposed to set the Max Pressure value BEFORE you collect data"); 01962 ERROR2IF(Pressure > m_MaxPressure, FALSE, "Pressure is greater than maximum value in CDistanceSampler::CollectData"); 01963 01964 BOOL ok = FALSE; 01965 // first up, if we are initialised to -1 then this is the first point, which we want 01966 if (m_DistanceSinceLastSample == -1) 01967 { 01968 if (m_ScalePressure != 1.0) 01969 Pressure = (UINT32)(m_ScalePressure * Pressure); 01970 CSampleItem TheItem(Coord, 0, Pressure); 01971 ok = SetAt(0, TheItem); 01972 m_DistanceSinceLastSample = 0; 01973 // TRACEUSER( "Diccon", _T("Recording pressure %d at 0\n"), Pressure); 01974 m_LastItemStored = TheItem; 01975 m_LastItem = TheItem; 01976 m_LastCoord = Coord; 01977 01978 } 01979 else 01980 { 01981 // find out how far we've gone 01982 MILLIPOINT Dist = (MILLIPOINT)Coord.Distance(m_LastItem.m_Coord); 01983 m_DistanceSinceLastData = Dist; 01984 m_DistanceSinceLastSample += Dist; 01985 m_TotalDistance += Dist; 01986 // TRACEUSER( "Diccon", _T("Received Pressure %d at Distance %d\n"), Pressure ,m_TotalDistance); 01987 // work out how many new items we need to make, and the proportional values to give to each 01988 double NumInsertItems = (double)m_DistanceSinceLastSample / (double)m_SampleDistance; 01989 if (NumInsertItems > 1) 01990 { 01991 if (m_ItemRemainder > 1) // if our remainder total adds up to >1 then add one more 01992 { 01993 NumInsertItems++; 01994 m_ItemRemainder--; 01995 } 01996 double ItemProportion = 1 / NumInsertItems; 01997 01998 // work out the values that we need to add on for each step 01999 MILLIPOINT XVal = (INT32)((double)(Coord.x - m_LastItem.m_Coord.x) * ItemProportion); 02000 MILLIPOINT YVal = (INT32)((double)(Coord.y - m_LastItem.m_Coord.y) * ItemProportion); 02001 double dPressure = (double)Pressure * m_ScalePressure; 02002 INT32 PressVal = (INT32)((dPressure - (double)m_LastItemStored.m_Pressure) * ItemProportion); 02003 m_ItemsInserted += (UINT32)NumInsertItems; 02004 //TRACEUSER( "Diccon", _T("INSERTED %d ITEMS\n"), m_ItemsInserted); 02005 CSampleItem TheItem = m_LastItemStored; 02006 while (NumInsertItems > 1) 02007 { 02008 m_DistanceSoFar += m_SampleDistance; 02009 TheItem.m_Pressure += PressVal; 02010 TheItem.m_Coord.x += XVal; 02011 TheItem.m_Coord.y += YVal; 02012 TheItem.m_Distance = m_DistanceSoFar; 02013 ok = SetNext(TheItem, TRUE); 02014 NumInsertItems--; 02015 m_DistanceSinceLastSample -= m_SampleDistance; 02016 //TRACEUSER( "Diccon", _T("Recording pressure %d at %d\n"), TheItem.m_Pressure, m_DistanceSoFar); 02017 } 02018 // add the remainder to our remainder counter 02019 m_ItemRemainder += NumInsertItems; 02020 02021 m_LastItemStored = TheItem; 02022 02023 } 02024 else 02025 ok = TRUE; 02026 } 02027 m_LastItem.m_Pressure = Pressure; 02028 m_LastItem.m_Coord = Coord; 02029 return ok; 02030 } 02031 02032 02033 /******************************************************************************************** 02034 02035 > BOOL CDistanceSampler::SetSampleRateFromSpacing(MILLIPOINT Spacing) 02036 02037 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02038 Created: 31/5/2000 02039 Inputs: Spacing - the spacing between brush objects 02040 Outputs: - 02041 Returns: TRUE so long as spacing is between bounds 02042 Purpose: Given the spacing between objects this works out the sample rate at which 02043 we want to retrieve objects 02044 Notes: 02045 ********************************************************************************************/ 02046 02047 BOOL CDistanceSampler::SetSampleRateFromSpacing(MILLIPOINT Spacing) 02048 { 02049 if (/*Spacing < MIN_BRUSH_SPACING ||*/ Spacing > MAX_BRUSH_SPACING) 02050 { 02051 ERROR3("Attempting to set invalid spacing value"); 02052 return FALSE; 02053 } 02054 02055 /* recall that sample rate 1 : Spacing = MIN_BRUSH_SPACING 02056 sample rate 2 : Spacing = 2 * MIN_BRUSH_SPACING 02057 sample rate 3 : Spacing = 3 * .. etc. */ 02058 02059 m_RetrievalSampleRate = ((double)Spacing / (double)MIN_BRUSH_SPACING) ; 02060 02061 return TRUE; 02062 } 02063 02064 02065 /******************************************************************************************** 02066 02067 > UINT32 CDistanceSampler::GetInternalIndexFromDistance(MILLIPOINT Distance) 02068 02069 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02070 Created: 31/5/2000 02071 Inputs: Distance - the distance along the path 02072 Outputs: - 02073 Returns: the internal index into the distance array at that distance, or -1 if something goes wrong 02074 Purpose: If you want to find out what index corresponds to Distance then call this, 02075 actually all it does is divide by the minimum spacing. Note that it will always 02076 round down. 02077 ERRORS: Negative distance being passed in, Distance resulting in index which is off the 02078 end of the array. 02079 Notes: 02080 ********************************************************************************************/ 02081 02082 INT32 CDistanceSampler::GetInternalIndexFromDistance(MILLIPOINT Distance) 02083 { 02084 if (Distance < 0) 02085 { 02086 ERROR3("Negative distance in CDistanceSampler::GetInternalIndexFromDistance"); 02087 return -1; 02088 } 02089 02090 INT32 Index = Distance / MIN_BRUSH_SPACING; 02091 02092 if (Index > (INT32)m_NumItems) 02093 Index = -1; 02094 return Index; 02095 } 02096 02097 02098 /******************************************************************************************** 02099 02100 > CDistanceSampler* CDistanceSampler::MakeCopy() 02101 02102 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02103 Created: 31/5/2000 02104 Inputs: - 02105 Outputs: - 02106 Returns: a copy of this object, unless something goes wrong (i.e memory) in which case NULL 02107 Purpose: Makes a copy of this sample data. Most of the work is done in the base class 02108 but we need to also copy a few members over 02109 02110 Notes: 02111 ********************************************************************************************/ 02112 02113 CDistanceSampler* CDistanceSampler::MakeCopy() 02114 { 02115 CDistanceSampler* pNewData = new CDistanceSampler; 02116 02117 if (pNewData == NULL) 02118 return NULL; 02119 02120 if (!pNewData->InitialiseData(m_NumItems)) 02121 { 02122 delete pNewData; 02123 return NULL; 02124 } 02125 02126 m_RetrievalSampleRate = 1; // make sure we get all the items 02127 02128 CSampleItem TheItem; 02129 02130 // unfortunately my implementation is a bit clumsy so we have to do the first item 02131 // by hand 02132 BOOL Getok = GetAt(0, &TheItem); 02133 BOOL Setok = pNewData->SetAt(0, TheItem); 02134 //TRACEUSER( "Diccon", _T("Copying pressure %d\n"), TheItem.m_Pressure); 02135 if (Getok == FALSE || Setok == FALSE) 02136 ERROR3("Failed to get or set first item in CSampleData::MakeCopy"); 02137 02138 UINT32 Counter = 1; 02139 // now we can loop through the rest 02140 while (Getok && Setok) 02141 { 02142 Getok = GetNext(&TheItem); 02143 Setok = pNewData->SetNext(TheItem); 02144 //TRACEUSER( "Diccon", _T("Copying pressure %d\n"), TheItem.m_Pressure); 02145 Counter++; 02146 } 02147 02148 pNewData->m_DistanceSoFar = TheItem.m_Distance; 02149 02150 if (Counter != m_NumItems) 02151 TRACEUSER( "Diccon", _T("CSampleData::MakeCopy - Num items copied = %d, Actual num items = %d\n"), Counter, m_NumItems); 02152 02153 // pNewData->SetSampleDistance(m_SampleDistance); 02154 return pNewData; 02155 } 02156 02157 02158 /******************************************************************************************** 02159 02160 > BOOL CDistanceSampler::GetDataSection(MILLIPOINT Start, MILLIPOINT End, CDistanceSampler* pSection) 02161 02162 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02163 Created: 12/6/2000 02164 Inputs: Start, End - the distances between which we want to get the data from 02165 pSection - pointer to an allocated CDistanceSampler 02166 Outputs: Initialises pSection with data between the two distances 02167 Returns: TRUE if successful, FALSE if something went wrong 02168 Purpose: Retrieves the data between Start and End and puts it into the sampler provided. 02169 02170 Errors: if Start or End are invalid, or if we don't have a sample array 02171 See Also: CSampleData::GetArraySection 02172 02173 Notes: If this fn. goes wrong you are responsible for deleting the CDistanceSampler 02174 ********************************************************************************************/ 02175 02176 BOOL CDistanceSampler::GetDataSection(MILLIPOINT Start, MILLIPOINT End, CDistanceSampler* pSection) 02177 { 02178 ERROR2IF(pSection == NULL, FALSE, "Sampler is NULL in CDistanceSampler::GetDataSection"); 02179 02180 if (Start < 0 || End < 0 || (End <= Start)) 02181 { 02182 ERROR3("Invalid distances in CSampleData::ReSample"); 02183 return FALSE; 02184 } 02185 // I guess if the caller hasn't allocated the sampler then we can do it, under duress.. 02186 if (pSection == NULL) 02187 { 02188 ERROR3("You haven't initialised the distance sampler. Well I suppose I can do it for you..."); 02189 pSection = new CDistanceSampler; 02190 if (pSection == NULL) 02191 { 02192 ERROR3("Well actually I can't, sorry must bail"); 02193 return FALSE; 02194 } 02195 } 02196 // get the indexes of the start and end points 02197 INT32 StartIndex = GetInternalIndexFromDistance(Start); 02198 INT32 EndIndex = GetInternalIndexFromDistance(End); 02199 02200 if (StartIndex == -1 || EndIndex == -1) 02201 { 02202 ERROR3("Error getting indexes in CDistanceSampler::ReSample"); 02203 return FALSE; 02204 } 02205 02206 // figure out how many items in the new length 02207 INT32 NewNumItems = (EndIndex - StartIndex) / MIN_BRUSH_SPACING; 02208 02209 // initialise the data 02210 if (!pSection->InitialiseData(NewNumItems)) 02211 return FALSE; 02212 02213 // call the helper function to do the work 02214 BOOL ok = GetArraySection((UINT32)StartIndex, (UINT32)EndIndex, pSection->GetSampleArray()); 02215 if (ok) 02216 pSection->SetNumItemsFromArraySize(); 02217 02218 return ok; 02219 } 02220 02221 02222 02223 /******************************************************************************************** 02224 02225 > BOOL CDistanceSampler::ReSample(MILLIPOINT NewLength) 02226 02227 Author: Diccon_Yamanaka (Xara Group Ltd) <camelotdev@xara.com> 02228 Created: 31/5/2000 02229 Inputs: NewLength - the new length to sample over 02230 Outputs: - 02231 Returns: TRUE if all went well, FALSE if not 02232 Purpose: If we want to change the distance that we sampled over then we must resample 02233 the data to make it fit. 02234 02235 Notes: In truth most of the work is done in the base class. Here we simply calculate the 02236 new number of items that we need and pass it along 02237 ********************************************************************************************/ 02238 02239 BOOL CDistanceSampler::ReSample(MILLIPOINT NewLength) 02240 { 02241 //checks 02242 if (NewLength <= 0 || m_pSampleData == NULL) 02243 { 02244 ERROR3("Invalid entry conditions in CDistanceSampler::ReSample"); 02245 return FALSE; 02246 } 02247 02248 // find out the new number of items 02249 INT32 NewNumItems = NewLength / MIN_BRUSH_SPACING; 02250 02251 m_DistanceSoFar = NewLength; 02252 02253 BOOL ok = ReSampleArray(&m_pSampleData, NewNumItems); 02254 if (ok) 02255 SetNumItemsFromArraySize(); // make sure our number of items is up to date 02256 02257 return ok; 02258 02259 }