diff --git a/.gitignore b/.gitignore index 2f01155..904b243 100644 --- a/.gitignore +++ b/.gitignore @@ -56,7 +56,7 @@ Indicators/ Librairies/ Logs/ Presets/ -/Profiles -/Scripts -/Services -/Shared Projets +Profiles/ +Scripts/ +Services/ +Shared Projets/ diff --git a/Experts/Nkanven/Framework EA/Grid/GridEA.ex5 b/Experts/Nkanven/Framework EA/Grid/GridEA.ex5 index 72df996..68f797d 100644 Binary files a/Experts/Nkanven/Framework EA/Grid/GridEA.ex5 and b/Experts/Nkanven/Framework EA/Grid/GridEA.ex5 differ diff --git a/Experts/Nkanven/Framework EA/Grid/GridEA.mq5 b/Experts/Nkanven/Framework EA/Grid/GridEA.mq5 index 396696b..922913b 100644 --- a/Experts/Nkanven/Framework EA/Grid/GridEA.mq5 +++ b/Experts/Nkanven/Framework EA/Grid/GridEA.mq5 @@ -101,6 +101,8 @@ int OnInit() // Set up the signals // EntrySignal = new CSignalGrid(); + EntrySignal.SetMaxRiskPerTrade(InpMaxRiskPerTrade); + EntrySignal.setMmagic(InpMagicNumber); //EntrySignal.AddIndicator(Indicator1, 0); ExitSignal = new CSignalGrid(); diff --git a/Include/A_EntriesManagement.mqh b/Include/A_EntriesManagement.mqh deleted file mode 100644 index 893777e..0000000 Binary files a/Include/A_EntriesManagement.mqh and /dev/null differ diff --git a/Include/A_HistoryChecker.mqh b/Include/A_HistoryChecker.mqh deleted file mode 100644 index cce9256..0000000 Binary files a/Include/A_HistoryChecker.mqh and /dev/null differ diff --git a/Include/A_LotSizeCal.mqh b/Include/A_LotSizeCal.mqh deleted file mode 100644 index 79f5c11..0000000 --- a/Include/A_LotSizeCal.mqh +++ /dev/null @@ -1,62 +0,0 @@ -//+------------------------------------------------------------------+ -//| A_LotSizeCal.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" - -//Lot Size Calculator -void LotSizeCalculate(double SL=0) - { -//If the position size is dynamic - if(RiskDefaultSize==RISK_DEFAULT_AUTO) - { - //If the stop loss is not zero then calculate the lot size - if(SL!=0) - { - double RiskBaseAmount=0; - //TickValue is the value of the individual price increment for 1 lot of the instrument, expressed in the account currenty - TickValue=SymbolInfoDouble(Symb,SYMBOL_TRADE_TICK_VALUE); - //Define the base for the risk calculation depending on the parameter chosen - if(RiskBase==RISK_BASE_BALANCE) - RiskBaseAmount=AccountInfoDouble(ACCOUNT_BALANCE); - if(RiskBase==RISK_BASE_EQUITY) - RiskBaseAmount=AccountInfoDouble(ACCOUNT_EQUITY); - if(RiskBase==RISK_BASE_FREEMARGIN) - RiskBaseAmount=AccountInfoDouble(ACCOUNT_FREEMARGIN); - //Calculate the Position Size - Print("Multiplier ", lotMultiplier, "Before lot multiplier ", (RiskBaseAmount*MaxRiskPerTrade/100)/(SL*TickValue)); - Print("RiskBaseAmount ", RiskBaseAmount, " MaxRiskPerTrade ", MaxRiskPerTrade, "Stop loss ", SL, " TickValue ", TickValue); - - LotSize=((RiskBaseAmount*MaxRiskPerTrade/100)/(SL*TickValue)); - - Print("After lot multiplier ", LotSize, " Lot multiplier ", lotMultiplier); - if(ActiveMartingale) - { - LotSize = LotSize * lotMultiplier; - } - } - //If the stop loss is zero then the lot size is the default one - if(SL==0) - { - LotSize=DefaultLotSize; - } - } -//Normalize the Lot Size to satisfy the allowed lot increment and minimum and maximum position size - LotSize=MathFloor(LotSize/SymbolInfoDouble(Symb,SYMBOL_VOLUME_STEP))*SymbolInfoDouble(Symb,SYMBOL_VOLUME_STEP); - -//Limit the lot size in case it is greater than the maximum allowed by the user - if(LotSize>MaxLotSize) - LotSize=MaxLotSize; -//Limit the lot size in case it is greater than the maximum allowed by the broker - if(LotSize>SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX)) - LotSize=SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX); - Print("Lot ", LotSize, " Max lot ", SymbolInfoDouble(Symb,SYMBOL_VOLUME_MAX)); -//If the lot size is too small then set it to 0 and don't trade - if(LotSize < SymbolInfoDouble(Symb,SYMBOL_VOLUME_MIN)) - { - LotSize=0; - Print("Lot size too small"); - } - } diff --git a/Include/A_Parameters.mqh b/Include/A_Parameters.mqh deleted file mode 100644 index 42702da..0000000 --- a/Include/A_Parameters.mqh +++ /dev/null @@ -1,213 +0,0 @@ -//+------------------------------------------------------------------+ -//| A_Parameters.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" -//+------------------------------------------------------------------+ -//| defines | -//+------------------------------------------------------------------+ - -//-ENUMERATIVE VARIABLES-// -//Enumerative variables are useful to associate numerical values to easy to remember strings -//It is similar to constants but also helps if the variable is set from the input page of the EA -//The text after the // is what you see in the input paramenters when the EA loads -//It is good practice to place all the enumberative at the start - -//Enumerative for the entry signal value -enum ENUM_SIGNAL_ENTRY - { - SIGNAL_ENTRY_NEUTRAL=0, //SIGNAL ENTRY NEUTRAL - SIGNAL_ENTRY_BUY=1, //SIGNAL ENTRY BUY - SIGNAL_ENTRY_SELL=-1, //SIGNAL ENTRY SELL - }; - -//Enumerative for the exit signal value -enum ENUM_SIGNAL_EXIT - { - SIGNAL_EXIT_NEUTRAL=0, //SIGNAL EXIT NEUTRAL - SIGNAL_EXIT_BUY=1, //SIGNAL EXIT BUY - SIGNAL_EXIT_SELL=-1, //SIGNAL EXIT SELL - SIGNAL_EXIT_ALL=2, //SIGNAL EXIT ALL - }; - -//Enumerative for the allowed trading direction -enum ENUM_TRADING_ALLOW_DIRECTION - { - TRADING_ALLOW_BOTH=0, //ALLOW BOTH BUY AND SELL - TRADING_ALLOW_BUY=1, //ALLOW BUY ONLY - TRADING_ALLOW_SELL=-1, //ALLOW SELL ONLY - }; - -//Enumerative for the base used for risk calculation -enum ENUM_RISK_BASE - { - RISK_BASE_EQUITY=1, //EQUITY - RISK_BASE_BALANCE=2, //BALANCE - RISK_BASE_FREEMARGIN=3, //FREE MARGIN - }; - -//Enumerative for the default risk size -enum ENUM_RISK_DEFAULT_SIZE - { - RISK_DEFAULT_FIXED=1, //FIXED SIZE - RISK_DEFAULT_AUTO=2, //AUTOMATIC SIZE BASED ON RISK - }; - -//Enumerative for the Stop Loss mode -enum ENUM_MODE_SL - { - SL_FIXED=0, //FIXED STOP LOSS - SL_AUTO=1, //AUTOMATIC STOP LOSS - }; - -//Enumerative for the Take Profit Mode -enum ENUM_MODE_TP - { - TP_FIXED=0, //FIXED TAKE PROFIT - TP_AUTO=1, //AUTOMATIC TAKE PROFIT - }; - -//Enumerative for the stop loss calculation -enum ENUM_MODE_SL_BY - { - SL_BY_POINTS=0, //STOP LOSS PASSED IN POINTS - SL_BY_PRICE=1, //STOP LOSS PASSED BY PRICE - }; - -//Enumerative for candle type -enum ENUM_CANDLE_TYPE - { - NEUTRAL_CANDLE=0, - BEARISH_CANDLE=1, - BULLISH_CANDLE=2, - }; - -//Enumerative for price momentum -enum ENUM_PRICE_MOMENTUM - { - UP=2, - DOWN=1, - NEUTRAL=0, - }; - -struct LastTransaction - { - string time; - int type; - double profit; - } lt; - -//-INPUT PARAMETERS-// -//The input parameters are the ones that can be set by the user when launching the EA -//If you place a comment following the input variable this will be shown as description of the field - -//This is where you should include the input parameters for your entry and exit signals -input string Comment_strategy="=========="; //Entry And Exit Settings -//Add in this section the parameters for the indicators used in your entry and exit - -//General input parameters -input string Comment_0="=========="; //Risk Management Settings -input ENUM_RISK_DEFAULT_SIZE RiskDefaultSize=RISK_DEFAULT_AUTO; //Position Size Mode -input double DefaultLotSize=1; //Position Size (if fixed or if no stop loss defined) -input ENUM_RISK_BASE RiskBase=RISK_BASE_BALANCE; //Risk Base -input double MaxRiskPerTrade=0.5; //Percentage To Risk Each Trade -input double MinLotSize=0.01; //Minimum Position Size Allowed -input double MaxLotSize=100; //Maximum Position Size Allowed - -input string Comment_1="=========="; //Trading Hours Settings -input bool UseTradingHours=false; //Limit Trading Hours -input string TradingHourStart="01"; //Trading Start Hour (Broker Server Hour) -input string TradingHourEnd="23"; //Trading End Hour (Broker Server Hour) -input string TradingStartMin="30"; //Trading Start minute (Broker Server Hour) -input string TradingEndMin="00"; //Trading End minute - -input string Comment_2="=========="; //Stop Loss And Take Profit Settings -input ENUM_MODE_SL StopLossMode=SL_AUTO; //Stop Loss Mode -input int DefaultStopLoss=0; //Default Stop Loss In Points (0=No Stop Loss) -input int MinStopLoss=0; //Minimum Allowed Stop Loss In Points -input int MaxStopLoss=5000; //Maximum Allowed Stop Loss In Points -input bool AtrStopLoss=false; //Set Stop loss based on ATR -input int atr_sl_factor=3; //Multiplicator for ATR stop loss -input ENUM_MODE_TP TakeProfitMode=TP_AUTO; //Take Profit Mode -input int DefaultTakeProfit=0; //Default Take Profit In Points (0=No Take Profit) -input int MinTakeProfit=0; //Minimum Allowed Take Profit In Points -input int MaxTakeProfit=5000; //Maximum Allowed Take Profit In Points -input double TakeProfitPercent=1.0; //Take Profit percent on risk base -input double Breakevent=1.0; //Minimum Profit to breakeven -input bool ProfitRun=true; -input bool ActiveMartingale=false; - -input string Comment_3="=========="; //Trailing Stop Settings -input bool UseTrailingStop=false; //Use Trailing Stop - -input string Comment_4="=========="; //Additional Settings -input int MagicNumber=0; //Magic Number For The Orders Opened By This EA -input string OrderNote=""; //Comment For The Orders Opened By This EA -input int Slippage=5; //Slippage in points -input double MaxSpread=10.0; //Maximum Allowed Spread To Trade In Points - -input string Comment_5="==========="; //Zigzag indicator setting -input int Depth=5; -input int Deviation=5; -input int Backstep=3; -input int GapPoint=100; //Minimum gap between peaks -input int Sensitivity=2; //Minimum peak at same level -input int LookBack=50; //Maximum peak to consider - -input int NumberOfCandles=3; - -//-GLOBAL VARIABLES-// -//The variables included in this section are global, hence they can be used in any part of the code -string Symb=Symbol(), server_time; - -long current_chart_id = ChartID(); - -bool IsPreChecksOk=false; //Indicates if the pre checks are satisfied -bool IsNewCandle=false; //Indicates if this is a new candle formed -bool IsSpreadOK=false; //Indicates if the spread is low enough to trade -bool IsOperatingHours=false; //Indicates if it is possible to trade at the current time (server time) -bool IsTradedThisBar=false; //Indicates if an order was already executed in the current candle -bool In_Trade = true; //Indicates if trade range has been formed -bool CanBuy = true; -bool CanSell = true; -bool ClosePosition = false; -bool FollowProfit = false; -bool UpTrendingMarket = false; -bool DownTrendingMarket = false; - -double TickValue=0; //Value of a tick in account currency at 1 lot -double LotSize=0; //Lot size for the position -double Tick_Size = SymbolInfoDouble(Symb,SYMBOL_TRADE_TICK_SIZE); //Tick size -double High[]; -double Low[]; -double PositionProfit; - -//Indicators - -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -long Spread = SymbolInfoInteger(Symb,SYMBOL_SPREAD) / 100; //Check the impact. It's originally a double -int OrderOpRetry=10; //Number of attempts to retry the order submission -int TotalOpenOrders=0; //Number of total open orders -int TotalOpenBuy=0; //Number of total open buy orders -int TotalOpenSell=0; //Number of total open sell orders -int StopLossBy=SL_BY_POINTS; //How the stop loss is passed for the lot size calculation -double lotMultiplier =1; //Adust lot size according to loosing trades -int candleCounter =0; -double firstCandleOpen =0; -double lastCandleClose=0; -double ProfitRunTargetPercent=10.0; - -datetime LastBarTraded; - -MqlDateTime dt; -MqlTick last_tick; - -ENUM_SIGNAL_ENTRY SignalEntry=SIGNAL_ENTRY_NEUTRAL; //Entry signal variable -ENUM_SIGNAL_EXIT SignalExit=SIGNAL_EXIT_NEUTRAL; -ENUM_CANDLE_TYPE candleType=NEUTRAL_CANDLE; -ENUM_PRICE_MOMENTUM priceMomentum=NEUTRAL; -//+------------------------------------------------------------------+ diff --git a/Include/A_PositionsManager.mqh b/Include/A_PositionsManager.mqh deleted file mode 100644 index ac8a2b1..0000000 --- a/Include/A_PositionsManager.mqh +++ /dev/null @@ -1,123 +0,0 @@ -//+------------------------------------------------------------------+ -//| A_PositionsManager.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" -CTrade trade; - -//Scan all positions to find the ones submitted by the EA -//NOTE This function is defined as bool because we want to return true if it is successful and false if it fails -bool ScanPositions() - { - -//Scan all the orders, retrieving some of the details - TotalOpenOrders = 0; - TotalOpenBuy = 0; - TotalOpenSell = 0; - for(int i=0; iLastBarTraded || LastBarTraded==0) - LastBarTraded=(datetime)PositionGetInteger(POSITION_TIME); - } - Print("Total positions ", TotalOpenOrders, " - Total buys ", TotalOpenBuy, " - Total sells ", TotalOpenSell); - return true; - } - -// We declare a function CloseOpenPositions of type int and we want to return -// the number of positions that are closed. -void CloseOpenPositions() - { - - int TotalClose=0; // We want to count how many orders have been closed. - int c_slippage = Slippage; - Print("Close position status ", ClosePosition); -// Normalization of the slippage. - if(_Digits==3 || _Digits==5) - { - c_slippage=c_slippage*10; - } - -// We scan all the orders backwards. -// This is required as if we start from the first order, we will have problems with the counters and the loop. - for(int i=PositionsTotal()-1; i>=0; i--) - { - - ulong ticket = PositionGetTicket(i); - - Print("Position profit is ", PositionGetDouble(POSITION_PROFIT)); - PositionProfit = PositionGetDouble(POSITION_PROFIT); - /*if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && iClose(Symb, PERIOD_CURRENT, 1) < Senkouspanb && iClose(Symb, PERIOD_CURRENT, 1) < Senkouspana) - { - // We select the order of index i, selecting by position and from the pool of market/pending trades. - //If the selection is successful we try to close the order. - if(trade.PositionClose(ticket, c_slippage)) - { - TotalClose++; - } - else - { - // If the order fails to be closed, we print the error. - Print("Order failed to close with error - ",GetLastError()); - } - } - - if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && iClose(Symb, PERIOD_CURRENT, 1) > Senkouspanb && iClose(Symb, PERIOD_CURRENT, 1) > Senkouspana) - { - // We select the order of index i, selecting by position and from the pool of market/pending trades. - //If the selection is successful we try to close the order. - if(trade.PositionClose(ticket, c_slippage)) - { - TotalClose++; - } - else - { - // If the order fails to be closed, we print the error. - Print("Order failed to close with error - ",GetLastError()); - } - }*/ - - if(ClosePosition) - { - if(trade.PositionClose(ticket, c_slippage)) - { - TotalClose++; - ClosePosition = false; - } - else - { - // If the order fails to be closed, we print the error. - Print("Order failed to close with error - ",GetLastError()); - } - } - // We can use a delay if the execution is too fast. - // Sleep() will wait X milliseconds before proceeding with the code. - // Sleep(300); - } - } -//+------------------------------------------------------------------+ diff --git a/Include/A_TradeManager.mqh b/Include/A_TradeManager.mqh deleted file mode 100644 index fa829a9..0000000 --- a/Include/A_TradeManager.mqh +++ /dev/null @@ -1,23 +0,0 @@ -//+------------------------------------------------------------------+ -//| A_TradeManager.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" - -void ProfitRunner() - { - if(ProfitRun) - { - if(iClose(Symb, _Period, 1) < iClose(Symb, _Period, 2) && TotalOpenBuy > 0) - { - ClosePosition = true; - } - if(iClose(Symb, _Period, 1) > iClose(Symb, _Period, 2) && TotalOpenSell > 0) - { - ClosePosition = true; - } - } - Print("Looking to close this position ", ClosePosition); - } \ No newline at end of file diff --git a/Include/A_TradingHour.mqh b/Include/A_TradingHour.mqh deleted file mode 100644 index 72d352a..0000000 --- a/Include/A_TradingHour.mqh +++ /dev/null @@ -1,27 +0,0 @@ -//+------------------------------------------------------------------+ -//| A_TradingHour.mqh | -//| Copyright 2021, Nkondog Anselme Venceslas | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2021, Nkondog Anselme Venceslas" -#property link "https://www.mql5.com" -//+------------------------------------------------------------------+ -//| defines | -//+------------------------------------------------------------------+ -// #define MacrosHello "Hello, world!" -// #define MacrosYear 2010 -//+------------------------------------------------------------------+ -//| DLL imports | -//+------------------------------------------------------------------+ -// #import "user32.dll" -// int SendMessageA(int hWnd,int Msg,int wParam,int lParam); -// #import "my_expert.dll" -// int ExpertRecalculate(int wParam,int lParam); -// #import -//+------------------------------------------------------------------+ -//| EX5 imports | -//+------------------------------------------------------------------+ -// #import "stdlib.ex5" -// string ErrorDescription(int error_code); -// #import -//+------------------------------------------------------------------+ diff --git a/Include/Arrays/Array.mqh b/Include/Arrays/Array.mqh deleted file mode 100644 index b78f528..0000000 --- a/Include/Arrays/Array.mqh +++ /dev/null @@ -1,182 +0,0 @@ -//+------------------------------------------------------------------+ -//| Array.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CArray | -//| Purpose: Base class of dynamic arrays. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CArray : public CObject - { -protected: - int m_step_resize; // increment size of the array - int m_data_total; // number of elements - int m_data_max; // maximmum size of the array without memory reallocation - int m_sort_mode; // mode of array sorting - -public: - CArray(void); - ~CArray(void); - //--- methods of access to protected data - int Step(void) const { return(m_step_resize); } - bool Step(const int step); - int Total(void) const { return(m_data_total); } - int Available(void) const { return(m_data_max-m_data_total); } - int Max(void) const { return(m_data_max); } - bool IsSorted(const int mode=0) const { return(m_sort_mode==mode); } - int SortMode(void) const { return(m_sort_mode); } - //--- cleaning method - void Clear(void) { m_data_total=0; } - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - //--- sorting method - void Sort(const int mode=0); - -protected: - virtual void QuickSort(int beg,int end,const int mode=0) { m_sort_mode=-1; } - //--- templates for methods of searching for minimum and maximum - template - int Minimum(const T &data[],const int start,const int count) const; - template - int Maximum(const T &data[],const int start,const int count) const; - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CArray::CArray(void) : m_step_resize(16), - m_data_total(0), - m_data_max(0), - m_sort_mode(-1) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CArray::~CArray(void) - { - } -//+------------------------------------------------------------------+ -//| Method Set for variable m_step_resize | -//+------------------------------------------------------------------+ -bool CArray::Step(const int step) - { -//--- check - if(step>0) - { - m_step_resize=step; - return(true); - } -//--- failure - return(false); - } -//+------------------------------------------------------------------+ -//| Sorting an array in ascending order | -//+------------------------------------------------------------------+ -void CArray::Sort(const int mode) - { -//--- check - if(IsSorted(mode)) - return; - m_sort_mode=mode; - if(m_data_total<=1) - return; -//--- sort - QuickSort(0,m_data_total-1,mode); - } -//+------------------------------------------------------------------+ -//| Writing header of array to file | -//+------------------------------------------------------------------+ -bool CArray::Save(const int file_handle) - { -//--- check handle - if(file_handle!=INVALID_HANDLE) - { - //--- write start marker - 0xFFFFFFFFFFFFFFFF - if(FileWriteLong(file_handle,-1)==sizeof(long)) - { - //--- write array type - if(FileWriteInteger(file_handle,Type(),INT_VALUE)==INT_VALUE) - return(true); - } - } -//--- failure - return(false); - } -//+------------------------------------------------------------------+ -//| Reading header of array from file | -//+------------------------------------------------------------------+ -bool CArray::Load(const int file_handle) - { -//--- check handle - if(file_handle!=INVALID_HANDLE) - { - //--- read and check start marker - 0xFFFFFFFFFFFFFFFF - if(FileReadLong(file_handle)==-1) - { - //--- read and check array type - if(FileReadInteger(file_handle,INT_VALUE)==Type()) - return(true); - } - } -//--- failure - return(false); - } -//+------------------------------------------------------------------+ -//| Find minimum of array | -//+------------------------------------------------------------------+ -template -int CArray::Minimum(const T &data[],const int start,const int count) const - { - int real_count; -//--- check for empty array - if(m_data_total<1) - { - SetUserError(ERR_USER_ARRAY_IS_EMPTY); - return(-1); - } - //--- check for start is out of range - if(start<0 || start>=m_data_total) - { - SetUserError(ERR_USER_ITEM_NOT_FOUND); - return(-1); - } -//--- compute count of elements - real_count=(count==WHOLE_ARRAY || start+count>m_data_total) ? m_data_total-start : count; -#ifdef __MQL5__ - return(ArrayMinimum(data,start,real_count)); -#else - return(ArrayMinimum(data,real_count,start)); -#endif - } -//+------------------------------------------------------------------+ -//| Find maximum of array | -//+------------------------------------------------------------------+ -template -int CArray::Maximum(const T &data[],const int start,const int count) const - { - int real_count; -//--- check for empty array - if(m_data_total<1) - { - SetUserError(ERR_USER_ARRAY_IS_EMPTY); - return(-1); - } - //--- check for start is out of range - if(start<0 || start>=m_data_total) - { - SetUserError(ERR_USER_ITEM_NOT_FOUND); - return(-1); - } -//--- compute count of elements - real_count=(count==WHOLE_ARRAY || start+count>m_data_total) ? m_data_total-start : count; -#ifdef __MQL5__ - return(ArrayMaximum(data,start,real_count)); -#else - return(ArrayMaximum(data,real_count,start)); -#endif - } -//+------------------------------------------------------------------+ diff --git a/Include/Arrays/ArrayChar.mqh b/Include/Arrays/ArrayChar.mqh deleted file mode 100644 index ea822b0..0000000 --- a/Include/Arrays/ArrayChar.mqh +++ /dev/null @@ -1,771 +0,0 @@ -//+------------------------------------------------------------------+ -//| ArrayChar.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Array.mqh" -//+------------------------------------------------------------------+ -//| Class CArrayChar. | -//| Purpose: Class of dynamic array of variables | -//| of char or uchar type. | -//| Derives from class CArray. | -//+------------------------------------------------------------------+ -class CArrayChar : public CArray - { -protected: - char m_data[]; // data array - -public: - CArrayChar(void); - ~CArrayChar(void); - //--- method of identifying the object - virtual int Type(void) const { return(TYPE_CHAR); } - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - //--- methods of managing dynamic memory - bool Reserve(const int size); - bool Resize(const int size); - bool Shutdown(void); - //--- methods of filling the array - bool Add(const char element); - bool AddArray(const char &src[]); - bool AddArray(const CArrayChar *src); - bool Insert(const char element,const int pos); - bool InsertArray(const char &src[],const int pos); - bool InsertArray(const CArrayChar *src,const int pos); - bool AssignArray(const char &src[]); - bool AssignArray(const CArrayChar *src); - //--- method of access to the array - char At(const int index) const; - char operator[](const int index) const { return(At(index)); } - //--- methods of searching for minimum and maximum - int Minimum(const int start,const int count) const { return(CArray::Minimum(m_data,start,count)); } - int Maximum(const int start,const int count) const { return(CArray::Maximum(m_data,start,count)); } - //--- methods of changing - bool Update(const int index,const char element); - bool Shift(const int index,const int shift); - //--- methods of deleting - bool Delete(const int index); - bool DeleteRange(int from,int to); - //--- methods for comparing arrays - bool CompareArray(const char &array[]) const; - bool CompareArray(const CArrayChar *array) const; - //--- methods for working with the sorted array - bool InsertSort(const char element); - int Search(const char element) const; - int SearchGreat(const char element) const; - int SearchLess(const char element) const; - int SearchGreatOrEqual(const char element) const; - int SearchLessOrEqual(const char element) const; - int SearchFirst(const char element) const; - int SearchLast(const char element) const; - int SearchLinear(const char element) const; - -protected: - virtual void QuickSort(int beg,int end,const int mode=0); - int QuickSearch(const char element) const; - int MemMove(const int dest,const int src,int count); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CArrayChar::CArrayChar(void) - { -//--- initialize protected data - m_data_max=ArraySize(m_data); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CArrayChar::~CArrayChar(void) - { - if(m_data_max!=0) - Shutdown(); - } -//+------------------------------------------------------------------+ -//| Moving the memory within a single array | -//+------------------------------------------------------------------+ -int CArrayChar::MemMove(const int dest,const int src,int count) - { - int i; -//--- check parameters - if(dest<0 || src<0 || count<0) - return(-1); -//--- check count - if(src+count>m_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayChar::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayChar::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayChar::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayChar::Add(const char element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayChar::AddArray(const char &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(CHAR_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayChar::Update(const int index,const char element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayChar::Shift(const int index,const int shift) - { - char tmp_char; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_char=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_char; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayChar::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayChar::CompareArray(const char &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_char=m_data[(beg+end)>>1]; - while(ip_char) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_char=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_char; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchLinear(const char element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_char=m_data[m]; - if(t_char==element) - break; - if(t_char>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::Search(const char element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchGreat(const char element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]<=element) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchLess(const char element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]>=element) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchGreatOrEqual(const char element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchLessOrEqual(const char element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchFirst(const char element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayChar::SearchLast(const char element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayChar::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayDouble::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayDouble::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayDouble::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayDouble::Add(const double element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayDouble::AddArray(const double &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(DBL_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayDouble::Update(const int index,const double element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayDouble::Shift(const int index,const int shift) - { - double tmp_double; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_double=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_double; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayDouble::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayDouble::CompareArray(const double &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_double=m_data[(beg+end)>>1]; - while(ip_double) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_double=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_double; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchLinear(const double element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_double=m_data[m]; - //--- compare with delta - if(MathAbs(t_double-element)<=m_delta) - break; - if(t_double>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::Search(const double element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - if(MathAbs(m_data[pos]-element)<=m_delta) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchGreat(const double element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - while(m_data[pos]<=element+m_delta) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchLess(const double element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - while(m_data[pos]>=element-m_delta) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchGreatOrEqual(const double element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchLessOrEqual(const double element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchFirst(const double element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - //--- compare with delta - while(MathAbs(m_data[pos]-element)<=m_delta) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayDouble::SearchLast(const double element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - //--- compare with delta - while(MathAbs(m_data[pos]-element)<=m_delta) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayDouble::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayFloat::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayFloat::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayFloat::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayFloat::Add(const float element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayFloat::AddArray(const float &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(FLT_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayFloat::Update(const int index,const float element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayFloat::Shift(const int index,const int shift) - { - float tmp_float; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_float=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_float; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayFloat::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayFloat::CompareArray(const float &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_float=m_data[(beg+end)>>1]; - while(ip_float) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_float=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_float; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchLinear(const float element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_float=m_data[m]; - //--- compare with delta - if(MathAbs(t_float-element)<=m_delta) - break; - if(t_float>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::Search(const float element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - if(MathAbs(m_data[pos]-element)<=m_delta) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchGreat(const float element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - while(m_data[pos]<=element+m_delta) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchLess(const float element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); -//--- compare with delta - while(m_data[pos]>=element-m_delta) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchGreatOrEqual(const float element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchLessOrEqual(const float element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchFirst(const float element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - //--- compare with delta - while(MathAbs(m_data[pos]-element)<=m_delta) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayFloat::SearchLast(const float element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - //--- compare with delta - while(MathAbs(m_data[pos]-element)<=m_delta) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayFloat::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayInt::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayInt::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayInt::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayInt::Add(const int element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayInt::AddArray(const int &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(INT_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayInt::Update(const int index,const int element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayInt::Shift(const int index,const int shift) - { - int tmp_int; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_int=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_int; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayInt::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayInt::CompareArray(const int &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_int=m_data[(beg+end)>>1]; - while(ip_int) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_int=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_int; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchLinear(const int element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_int=m_data[m]; - if(t_int==element) - break; - if(t_int>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::Search(const int element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchGreat(const int element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]<=element) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchLess(const int element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]>=element) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchGreatOrEqual(const int element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchLessOrEqual(const int element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchFirst(const int element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayInt::SearchLast(const int element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayInt::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayLong::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayLong::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayLong::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayLong::Add(const long element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayLong::AddArray(const long &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(LONG_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayLong::Update(const int index,const long element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayLong::Shift(const int index,const int shift) - { - long tmp_long; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_long=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_long; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayLong::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayLong::CompareArray(const long &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_long=m_data[(beg+end)>>1]; - while(ip_long) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_long=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_long; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchLinear(const long element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_long=m_data[m]; - if(t_long==element) - break; - if(t_long>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::Search(const long element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchGreat(const long element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]<=element) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchLess(const long element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]>=element) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchGreatOrEqual(const long element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchLessOrEqual(const long element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchFirst(const long element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayLong::SearchLast(const long element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayLong::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - { - //--- "physical" removal of the object (if necessary and possible) - if(m_free_mode && CheckPointer(m_data[dest+i])==POINTER_DYNAMIC) - delete m_data[dest+i]; - //--- - m_data[dest+i]=m_data[src+i]; - m_data[src+i]=NULL; - } - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayObj::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayObj::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_total>size) - { - //--- "physical" removal of the object (if necessary and possible) - if(m_free_mode) - for(int i=size;i=m_data_total) - return(NULL); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayObj::Update(const int index,CObject *element) - { -//--- check - if(index<0 || !CheckPointer(element) || index>=m_data_total) - return(false); -//--- "physical" removal of the object (if necessary and possible) - if(m_free_mode && CheckPointer(m_data[index])==POINTER_DYNAMIC) - delete m_data[index]; -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayObj::Shift(const int index,const int shift) - { - CObject *tmp_node; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_node=m_data[index]; - m_data[index]=NULL; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_node; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayObj::Delete(const int index) - { -//--- check - if(index>=m_data_total) - return(false); -//--- delete - if(index=0 && MemMove(index,index+1,m_data_total-index-1)<0) - return(false); - } - else - if(m_free_mode && CheckPointer(m_data[index])==POINTER_DYNAMIC) - delete m_data[index]; - m_data_total--; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Detach element from the specified position | -//+------------------------------------------------------------------+ -CObject *CArrayObj::Detach(const int index) - { - CObject *result; -//--- check - if(index>=m_data_total) - return(NULL); -//--- detach - result=m_data[index]; -//--- reset the array element, so as not remove the method MemMove - m_data[index]=NULL; - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - for(int i=to-from+1;i>0;i--,m_data_total--) - if(m_free_mode && CheckPointer(m_data[m_data_total-1])==POINTER_DYNAMIC) - delete m_data[m_data_total-1]; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Clearing of array without the release of memory | -//+------------------------------------------------------------------+ -void CArrayObj::Clear(void) - { -//--- "physical" removal of the object (if necessary and possible) - if(m_free_mode) - { - for(int i=0;i>1" is quick division by 2 - p_node=m_data[(beg+end)>>1]; - while(i0) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_node=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_node; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(beg0) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=mode; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Quick search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::QuickSearch(const CObject *element) const - { - int i,j,m=-1; - CObject *t_node; -//--- search - i=0; - j=m_data_total-1; - while(j>=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m==m_data_total-1) - break; - t_node=m_data[m]; - if(t_node.Compare(element,m_sort_mode)==0) - break; - if(t_node.Compare(element,m_sort_mode)>0) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::Search(const CObject *element) const - { - int pos; -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos].Compare(element,m_sort_mode)==0) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchGreat(const CObject *element) const - { - int pos; -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos].Compare(element,m_sort_mode)<=0) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchLess(const CObject *element) const - { - int pos; -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos].Compare(element,m_sort_mode)>=0) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchGreatOrEqual(const CObject *element) const - { -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=0) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchLessOrEqual(const CObject *element) const - { -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos].Compare(element,m_sort_mode)<=0) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchFirst(const CObject *element) const - { - int pos; -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos].Compare(element,m_sort_mode)==0) - { - while(m_data[pos].Compare(element,m_sort_mode)==0) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayObj::SearchLast(const CObject *element) const - { - int pos; -//--- check - if(m_data_total==0 || !CheckPointer(element) || m_sort_mode==-1) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos].Compare(element,m_sort_mode)==0) - { - while(m_data[pos].Compare(element,m_sort_mode)==0) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayObj::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayShort::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayShort::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayShort::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayShort::Add(const short element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayShort::AddArray(const short &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(SHORT_MAX); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayShort::Update(const int index,const short element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayShort::Shift(const int index,const int shift) - { - short tmp_short; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_short=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_short; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayShort::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayShort::CompareArray(const short &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_short=m_data[(beg+end)>>1]; - while(ip_short) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_short=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_short; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchLinear(const short element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_short=m_data[m]; - if(t_short==element) - break; - if(t_short>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::Search(const short element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchGreat(const short element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]<=element) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchLess(const short element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]>=element) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchGreatOrEqual(const short element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchLessOrEqual(const short element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchFirst(const short element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayShort::SearchLast(const short element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayShort::Save(const int file_handle) - { - int i=0; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;im_data_total) - count=m_data_total-src; - if(count<0) - return(-1); -//--- no need to copy - if(dest==src || count==0) - return(dest); -//--- check data total - if(dest+count>m_data_total) - { - if(m_data_max=0;i--) - m_data[dest+i]=m_data[src+i]; - } -//--- successful - return(dest); - } -//+------------------------------------------------------------------+ -//| Request for more memory in an array. Checks if the requested | -//| number of free elements already exists; allocates additional | -//| memory with a given step | -//+------------------------------------------------------------------+ -bool CArrayString::Reserve(const int size) - { - int new_size; -//--- check - if(size<=0) - return(false); -//--- resize array - if(Available()=size); - } -//+------------------------------------------------------------------+ -//| Resizing (with removal of elements on the right) | -//+------------------------------------------------------------------+ -bool CArrayString::Resize(const int size) - { - int new_size; -//--- check - if(size<0) - return(false); -//--- resize array - new_size=m_step_resize*(1+size/m_step_resize); - if(m_data_max!=new_size) - { - if((m_data_max=ArrayResize(m_data,new_size))==-1) - { - m_data_max=ArraySize(m_data); - return(false); - } - } - if(m_data_total>size) - m_data_total=size; -//--- result - return(m_data_max==new_size); - } -//+------------------------------------------------------------------+ -//| Complete cleaning of the array with the release of memory | -//+------------------------------------------------------------------+ -bool CArrayString::Shutdown(void) - { -//--- check - if(m_data_max==0) - return(true); -//--- clean - if(ArrayResize(m_data,0)==-1) - return(false); - m_data_total=0; - m_data_max=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array | -//+------------------------------------------------------------------+ -bool CArrayString::Add(const string element) - { -//--- check/reserve elements of array - if(!Reserve(1)) - return(false); -//--- add - m_data[m_data_total++]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Adding an element to the end of the array from another array | -//+------------------------------------------------------------------+ -bool CArrayString::AddArray(const string &src[]) - { - int num=ArraySize(src); -//--- check/reserve elements of array - if(!Reserve(num)) - return(false); -//--- add - for(int i=0;i=m_data_total) - return(""); -//--- result - return(m_data[index]); - } -//+------------------------------------------------------------------+ -//| Updating element in the specified position | -//+------------------------------------------------------------------+ -bool CArrayString::Update(const int index,const string element) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- update - m_data[index]=element; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Moving element from the specified position | -//| on the specified shift | -//+------------------------------------------------------------------+ -bool CArrayString::Shift(const int index,const int shift) - { - string tmp_string; -//--- check - if(index<0 || index+shift<0 || index+shift>=m_data_total) - return(false); - if(shift==0) - return(true); -//--- move - tmp_string=m_data[index]; - if(shift>0) - { - if(MemMove(index,index+1,shift)<0) - return(false); - } - else - { - if(MemMove(index+shift+1,index+shift,-shift)<0) - return(false); - } - m_data[index+shift]=tmp_string; - m_sort_mode=-1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Deleting element from the specified position | -//+------------------------------------------------------------------+ -bool CArrayString::Delete(const int index) - { -//--- check - if(index<0 || index>=m_data_total) - return(false); -//--- delete - if(indexto || from>=m_data_total) - return(false); -//--- delete - if(to>=m_data_total-1) - to=m_data_total-1; - if(MemMove(from,to+1,m_data_total-to-1)<0) - return(false); - m_data_total-=to-from+1; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Equality comparison of two arrays | -//+------------------------------------------------------------------+ -bool CArrayString::CompareArray(const string &array[]) const - { -//--- compare - if(m_data_total!=ArraySize(array)) - return(false); - for(int i=0;i>1" is quick division by 2 - p_string=m_data[(beg+end)>>1]; - while(ip_string) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - if(i<=j) - { - t_string=m_data[i]; - m_data[i++]=m_data[j]; - m_data[j]=t_string; - //--- control the output of the array bounds - if(j==0) - break; - j--; - } - } - if(begelement) - Insert(element,pos); - else - Insert(element,pos+1); -//--- restore the sorting flag after Insert(...) - m_sort_mode=0; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a array | -//+------------------------------------------------------------------+ -int CArrayString::SearchLinear(const string element) const - { -//--- check - if(m_data_total==0) - return(-1); -//--- - for(int i=0;i=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_string=m_data[m]; - if(t_string==element) - break; - if(t_string>element) - j=m-1; - else - i=m+1; - } -//--- position - return(m); - } -//+------------------------------------------------------------------+ -//| Search of position of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::Search(const string element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than | -//| specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchGreat(const string element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]<=element) - if(++pos==m_data_total) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than | -//| specified in the sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchLess(const string element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - while(m_data[pos]>=element) - if(pos--==0) - return(-1); -//--- position - return(pos); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is greater than or | -//| equal to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchGreatOrEqual(const string element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Search position of the first element which is less than or equal | -//| to the specified in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchLessOrEqual(const string element) const - { -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - for(int pos=QuickSearch(element);pos>=0;pos--) - if(m_data[pos]<=element) - return(pos); -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of first appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchFirst(const string element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(pos--==0) - break; - return(pos+1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Find position of last appearance of element in a sorted array | -//+------------------------------------------------------------------+ -int CArrayString::SearchLast(const string element) const - { - int pos; -//--- check - if(m_data_total==0 || !IsSorted()) - return(-1); -//--- search - pos=QuickSearch(element); - if(m_data[pos]==element) - { - while(m_data[pos]==element) - if(++pos==m_data_total) - break; - return(pos-1); - } -//--- not found - return(-1); - } -//+------------------------------------------------------------------+ -//| Writing array to file | -//+------------------------------------------------------------------+ -bool CArrayString::Save(const int file_handle) - { - int i=0,len; -//--- check - if(!CArray::Save(file_handle)) - return(false); -//--- write array length - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- write array - for(i=0;i -//+------------------------------------------------------------------+ -//| Class CList. | -//| Purpose: Provides the possibility of working with the list of | -//| CObject instances and its dervivatives | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CList : public CObject - { -protected: - CObject *m_first_node; // pointer to the first element of the list - CObject *m_last_node; // pointer to the last element of the list - CObject *m_curr_node; // pointer to the current element of the list - int m_curr_idx; // index of the current list item - int m_data_total; // number of elements - bool m_free_mode; // flag of the necessity of "physical" deletion of object - bool m_data_sort; // flag if the list is sorted or not - int m_sort_mode; // mode of sorting of array - -public: - CList(void); - ~CList(void); - //--- methods of access to protected data - bool FreeMode(void) const { return(m_free_mode); } - void FreeMode(bool mode) { m_free_mode=mode; } - int Total(void) const { return(m_data_total); } - bool IsSorted(void) const { return(m_data_sort); } - int SortMode(void) const { return(m_sort_mode); } - //--- method of identifying the object - virtual int Type(void) const { return(0x7779); } - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - //--- method of creating an element of the list - virtual CObject *CreateElement(void) { return(NULL); } - //--- methods of filling the list - int Add(CObject *new_node); - int Insert(CObject *new_node,int index); - //--- methods for navigating - int IndexOf(CObject *node); - CObject *GetNodeAtIndex(int index); - CObject *GetFirstNode(void); - CObject *GetPrevNode(void); - CObject *GetCurrentNode(void); - CObject *GetNextNode(void); - CObject *GetLastNode(void); - //--- methods for deleting - CObject *DetachCurrent(void); - bool DeleteCurrent(void); - bool Delete(int index); - void Clear(void); - //--- method for comparing lists - bool CompareList(CList *List); - //--- methods for changing - void Sort(int mode); - bool MoveToIndex(int index); - bool Exchange(CObject *node1,CObject *node2); - //--- method for searching - CObject *Search(CObject *element); -protected: - void QuickSort(int beg,int end,int mode); - CObject *QuickSearch(CObject *element); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CList::CList(void) : m_first_node(NULL), - m_last_node(NULL), - m_curr_node(NULL), - m_curr_idx(-1), - m_data_total(0), - m_free_mode(true), - m_data_sort(false), - m_sort_mode(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CList::~CList(void) - { - Clear(); - } -//+------------------------------------------------------------------+ -//| Method QuickSort | -//+------------------------------------------------------------------+ -void CList::QuickSort(int beg,int end,int mode) - { - int i,j,k; - CObject *i_ptr,*j_ptr,*k_ptr; -//--- - i_ptr=GetNodeAtIndex(i=beg); - j_ptr=GetNodeAtIndex(j=end); - while(i>1" is quick division by 2 - k_ptr=GetNodeAtIndex(k=(beg+end)>>1); - while(i0) - { - //--- control the output of the array bounds - if(j==0) - break; - j--; - j_ptr=j_ptr.Prev(); - } - if(i<=j) - { - Exchange(i_ptr,j_ptr); - i++; - i_ptr=GetNodeAtIndex(i); - //--- control the output of the array bounds - if(j==0) - break; - else - { - j--; - j_ptr=GetNodeAtIndex(j); - } - } - } - if(begm_data_total || index<0) - return(-1); -//--- adjust - if(index==-1) - { - if(m_curr_node==NULL) - return(Add(new_node)); - } - else - { - if(GetNodeAtIndex(index)==NULL) - return(Add(new_node)); - } -//--- no need to check m_curr_node - tmp_node=m_curr_node.Prev(); - new_node.Prev(tmp_node); - if(tmp_node!=NULL) - tmp_node.Next(new_node); - else - m_first_node=new_node; - new_node.Next(m_curr_node); - m_curr_node.Prev(new_node); - m_data_total++; - m_data_sort=false; - m_curr_node=new_node; -//--- result - return(index); - } -//+------------------------------------------------------------------+ -//| Get a pointer to the position of element in the list | -//+------------------------------------------------------------------+ -CObject *CList::GetNodeAtIndex(int index) - { - int i; - bool revers; - CObject *result; -//--- check - if(index>=m_data_total) - return(NULL); - if(index==m_curr_idx) - return(m_curr_node); -//--- optimize bust list - if(indexindex;i--) - { - result=result.Prev(); - if(result==NULL) - return(NULL); - } - } - else - { - //--- search from left to right - for(;i=m_data_total || !CheckPointer(m_curr_node)) - return(false); -//--- tune - if(m_curr_idx==index) - return(true); - if(m_curr_idx=i) - { - //--- ">>1" is quick division by 2 - m=(j+i)>>1; - if(m<0 || m>=m_data_total) - break; - t_node=GetNodeAtIndex(m); - if(t_node.Compare(element,m_sort_mode)==0) - break; - if(t_node.Compare(element,m_sort_mode)>0) - j=m-1; - else - i=m+1; - t_node=NULL; - } -//--- result - return(t_node); - } -//+------------------------------------------------------------------+ -//| Search position of an element in a sorted list | -//+------------------------------------------------------------------+ -CObject *CList::Search(CObject *element) - { - CObject *result; -//--- check - if(!CheckPointer(element) || !m_data_sort) - return(NULL); -//--- search - result=QuickSearch(element); -//--- result - return(result); - } -//+------------------------------------------------------------------+ -//| Writing list to file | -//+------------------------------------------------------------------+ -bool CList::Save(const int file_handle) - { - CObject *node; - bool result=true; -//--- check - if(!CheckPointer(m_curr_node) || file_handle==INVALID_HANDLE) - return(false); -//--- write start marker - 0xFFFFFFFFFFFFFFFF - if(FileWriteLong(file_handle,-1)!=sizeof(long)) - return(false); -//--- write type - if(FileWriteInteger(file_handle,Type(),INT_VALUE)!=INT_VALUE) - return(false); -//--- write list size - if(FileWriteInteger(file_handle,m_data_total,INT_VALUE)!=INT_VALUE) - return(false); -//--- sequential scannning of elements in the list using the call of method Save() - node=m_first_node; - while(node!=NULL) - { - result&=node.Save(file_handle); - node=node.Next(); - } -//--- successful - return(result); - } -//+------------------------------------------------------------------+ -//| Reading list from file | -//+------------------------------------------------------------------+ -bool CList::Load(const int file_handle) - { - uint i,num; - CObject *node; - bool result=true; -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- read and checking begin marker - 0xFFFFFFFFFFFFFFFF - if(FileReadLong(file_handle)!=-1) - return(false); -//--- read and checking type - if(FileReadInteger(file_handle,INT_VALUE)!=Type()) - return(false); -//--- read list size - num=FileReadInteger(file_handle,INT_VALUE); -//--- sequential creation of list items using the call of method Load() - Clear(); - for(i=0;i0) - p_node.Left(new_node); - else - p_node.Right(new_node); - new_node.Parent(p_node); - Balance(p_node); - } - else - m_root_node=new_node; -//--- result - return(result); - } -//+------------------------------------------------------------------+ -//| Method of removing a node from the tree | -//+------------------------------------------------------------------+ -bool CTree::Delete(CTreeNode *node) - { -//--- check - if(!CheckPointer(node)) - return(false); -//--- delete - if(Detach(node) && CheckPointer(node)==POINTER_DYNAMIC) - delete node; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Method of detaching node from the tree | -//+------------------------------------------------------------------+ -bool CTree::Detach(CTreeNode *node) - { - CTreeNode *curr_node,*tmp_node; - CTreeNode *nodeA,*nodeB; -//--- check - curr_node=node; - if(!CheckPointer(curr_node)) - return(false); -//--- detach - if(curr_node.BalanceL()>curr_node.BalanceR()) - { - nodeA=curr_node.Left(); - while(nodeA.Right()!=NULL) - nodeA=nodeA.Right(); - nodeB=nodeA.Parent(); - if(nodeB!=curr_node) - { - nodeB.Right(nodeA.Left()); - tmp_node=nodeB.Right(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeB); - tmp_node=curr_node.Left(); - nodeA.Left(tmp_node); - tmp_node.Parent(nodeA); - } - //--- left link of curr_node is already installed as it should be - curr_node.Left(NULL); - //--- transferring the right link of curr_node to nodeA - nodeA.Right(curr_node.Right()); - tmp_node=curr_node.Right(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - curr_node.Right(NULL); - //--- transferring the root link of curr_node to nodeA - tmp_node=curr_node.Parent(); - nodeA.Parent(tmp_node); - if(tmp_node!=NULL) - { - if(tmp_node.Left()==curr_node) - tmp_node.Left(nodeA); - else - tmp_node.Right(nodeA); - } - else - { - curr_node.Parent(NULL); - m_root_node=nodeA; - tmp_node=nodeA; - } - Balance(tmp_node); - } - else - { - if(curr_node.BalanceR()>0) - { - nodeA=curr_node.Right(); - while(nodeA.Left()!=NULL) - nodeA=nodeA.Left(); - nodeB=nodeA.Parent(); - if(nodeB!=curr_node) - { - nodeB.Left(nodeA.Right()); - tmp_node=nodeB.Left(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeB); - tmp_node=curr_node.Right(); - nodeA.Right(tmp_node); - tmp_node.Parent(nodeA); - } - //--- right link of curr_node is already installed as it should be - curr_node.Right(NULL); - //--- transferring the left link of curr_node to nodeA - nodeA.Left(curr_node.Left()); - tmp_node=curr_node.Left(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - curr_node.Left(NULL); - //--- transferring the root link of curr_node to nodeA - tmp_node=curr_node.Parent(); - nodeA.Parent(tmp_node); - if(tmp_node!=NULL) - { - if(tmp_node.Left()==curr_node) - tmp_node.Left(nodeA); - else - tmp_node.Right(nodeA); - } - else - { - curr_node.Parent(NULL); - m_root_node=nodeA; - tmp_node=nodeA; - } - Balance(tmp_node); - } - else - { - //--- node list - if(curr_node.Parent()==NULL) - m_root_node=NULL; - else - { - tmp_node=curr_node.Parent(); - if(tmp_node.Left()==curr_node) - tmp_node.Left(NULL); - else - tmp_node.Right(NULL); - curr_node.Parent(NULL); - } - Balance(curr_node.Parent()); - } - } -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Method of cleaning the tree | -//+------------------------------------------------------------------+ -void CTree::Clear(void) - { - if(CheckPointer(m_root_node)==POINTER_DYNAMIC) - delete m_root_node; - m_root_node=NULL; - } -//+------------------------------------------------------------------+ -//| Method of searching for a node in the tree | -//+------------------------------------------------------------------+ -CTreeNode *CTree::Find(const CTreeNode *node) - { - CTreeNode *result=m_root_node; -//--- find - while(result!=NULL && result.Compare(node)!=0) - result=result.GetNext(node); -//--- result - return(result); - } -//+------------------------------------------------------------------+ -//| Method of balancing the tree | -//+------------------------------------------------------------------+ -void CTree::Balance(CTreeNode *node) - { - CTreeNode *nodeA,*nodeB,*nodeC,*curr_node,*tmp_node; -//--- - curr_node=node; - while(curr_node!=NULL) - { - curr_node.RefreshBalance(); - if(MathAbs(curr_node.BalanceL()-curr_node.BalanceR())<=1) - curr_node=curr_node.Parent(); - else - { - if(curr_node.BalanceR()>curr_node.BalanceL()) - { - //--- rotation to the right - tmp_node=curr_node.Right(); - if(tmp_node.BalanceL()>tmp_node.BalanceR()) - { - //--- great rotation to the right - nodeA=curr_node; - nodeB=nodeA.Right(); - nodeC=nodeB.Left(); - nodeC.Parent(nodeA.Parent()); - tmp_node=nodeC.Parent(); - if(tmp_node!=NULL) - { - if(tmp_node.Right()==nodeA) - tmp_node.Right(nodeC); - else - tmp_node.Left(nodeC); - } - else - m_root_node=nodeC; - nodeA.Parent(nodeC); - nodeB.Parent(nodeC); - nodeA.Right(nodeC.Left()); - tmp_node=nodeA.Right(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - nodeC.Left(nodeA); - nodeB.Left(nodeC.Right()); - tmp_node=nodeB.Left(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeB); - nodeC.Right(nodeB); - if(m_root_node==nodeA) - m_root_node=nodeC; - curr_node=nodeC.Parent(); - } - else - { - //--- slight rotation to the right - nodeA=curr_node; - nodeB=nodeA.Right(); - nodeB.Parent(nodeA.Parent()); - tmp_node=nodeB.Parent(); - if(tmp_node!=NULL) - { - if(tmp_node.Right()==nodeA) - tmp_node.Right(nodeB); - else - tmp_node.Left(nodeB); - } - else - m_root_node=nodeB; - nodeA.Parent(nodeB); - nodeA.Right(nodeB.Left()); - tmp_node=nodeA.Right(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - nodeB.Left(nodeA); - if(m_root_node==nodeA) - m_root_node=nodeB; - curr_node=nodeB.Parent(); - } - } - else - { - //--- rotation to the left - tmp_node=curr_node.Left(); - if(tmp_node.BalanceR()>tmp_node.BalanceL()) - { - //--- great rotation to the left - nodeA=curr_node; - nodeB=nodeA.Left(); - nodeC=nodeB.Right(); - nodeC.Parent(nodeA.Parent()); - tmp_node=nodeC.Parent(); - if(tmp_node!=NULL) - { - if(tmp_node.Right()==nodeA) - tmp_node.Right(nodeC); - else - tmp_node.Left(nodeC); - } - else - m_root_node=nodeC; - nodeA.Parent(nodeC); - nodeB.Parent(nodeC); - nodeA.Left(nodeC.Right()); - tmp_node=nodeA.Left(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - nodeC.Right(nodeA); - nodeB.Right(nodeC.Left()); - tmp_node=nodeB.Right(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeB); - nodeC.Left(nodeB); - if(m_root_node==nodeA) - m_root_node=nodeC; - curr_node=nodeC.Parent(); - } - else - { - //--- small rotation to the left - nodeA=curr_node; - nodeB=nodeA.Left(); - nodeB.Parent(nodeA.Parent()); - tmp_node=nodeB.Parent(); - if(tmp_node!=NULL) - { - if(tmp_node.Right()==nodeA) - tmp_node.Right(nodeB); - else - tmp_node.Left(nodeB); - } - else - m_root_node=nodeB; - nodeA.Parent(nodeB); - nodeA.Left(nodeB.Right()); - tmp_node=nodeA.Left(); - if(tmp_node!=NULL) - tmp_node.Parent(nodeA); - nodeB.Right(nodeA); - if(m_root_node==nodeA) - m_root_node=nodeB; - curr_node=nodeB.Parent(); - } - } - } - } - } -//+------------------------------------------------------------------+ -//| Writing tree to file | -//+------------------------------------------------------------------+ -bool CTree::Save(const int file_handle) - { -//--- check - if(file_handle==INVALID_HANDLE) - return(false); - if(m_root_node==NULL) - return(true); -//--- result - return(m_root_node.SaveNode(file_handle)); - } -//+------------------------------------------------------------------+ -//| Reading tree from file | -//+------------------------------------------------------------------+ -bool CTree::Load(const int file_handle) - { -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- create root node only - Clear(); - Insert(CreateElement()); -//--- result - return(m_root_node.LoadNode(file_handle,m_root_node)); - } -//+------------------------------------------------------------------+ diff --git a/Include/Arrays/TreeNode.mqh b/Include/Arrays/TreeNode.mqh deleted file mode 100644 index fde1633..0000000 --- a/Include/Arrays/TreeNode.mqh +++ /dev/null @@ -1,174 +0,0 @@ -//+------------------------------------------------------------------+ -//| TreeNode.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CTreeNode. | -//| Purpose: Base class of node of binary tree CTree. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CTreeNode : public CObject - { -private: - CTreeNode *m_p_node; // link to node up - CTreeNode *m_l_node; // link to node left - CTreeNode *m_r_node; // link to node right - //--- variables - int m_balance; // balance of node - int m_l_balance; // balance of the left branch - int m_r_balance; // balance of the right branch - -public: - CTreeNode(void); - ~CTreeNode(void); - //--- methods of access to protected data - CTreeNode* Parent(void) const { return(m_p_node); } - void Parent(CTreeNode *node) { m_p_node=node; } - CTreeNode* Left(void) const { return(m_l_node); } - void Left(CTreeNode *node) { m_l_node=node; } - CTreeNode* Right(void) const { return(m_r_node); } - void Right(CTreeNode *node) { m_r_node=node; } - int Balance(void) const { return(m_balance); } - int BalanceL(void) const { return(m_l_balance); } - int BalanceR(void) const { return(m_r_balance); } - //--- method of identifying the object - virtual int Type(void) const { return(0x8888); } - //--- methods for controlling - int RefreshBalance(void); - CTreeNode *GetNext(const CTreeNode *node); - //--- methods for working with files - bool SaveNode(const int file_handle); - bool LoadNode(const int file_handle,CTreeNode *main); - -protected: - //--- method for creating an instance of class - virtual CTreeNode *CreateSample(void) { return(NULL); } - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CTreeNode::CTreeNode(void) : m_p_node(NULL), - m_l_node(NULL), - m_r_node(NULL), - m_balance(0), - m_l_balance(0), - m_r_balance(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CTreeNode::~CTreeNode(void) - { -//--- delete nodes of the next level - if(m_l_node!=NULL) - delete m_l_node; - if(m_r_node!=NULL) - delete m_r_node; - } -//+------------------------------------------------------------------+ -//| Calculating the balance of the node | -//+------------------------------------------------------------------+ -int CTreeNode::RefreshBalance(void) - { -//--- calculate the balance of the left branch - if(m_l_node==NULL) - m_l_balance=0; - else - m_l_balance=m_l_node.RefreshBalance(); -//--- calculate the balance of the right branch - if(m_r_node==NULL) - m_r_balance=0; - else - m_r_balance=m_r_node.RefreshBalance(); -//--- calculate the balance of the node - if(m_r_balance>m_l_balance) - m_balance=m_r_balance+1; - else - m_balance=m_l_balance+1; -//--- result - return(m_balance); - } -//+------------------------------------------------------------------+ -//| Selecting next node | -//+------------------------------------------------------------------+ -CTreeNode *CTreeNode::GetNext(const CTreeNode *node) - { - if(Compare(node)>0) - return(m_l_node); -//--- result - return(m_r_node); - } -//+------------------------------------------------------------------+ -//| Writing node data to file | -//+------------------------------------------------------------------+ -bool CTreeNode::SaveNode(const int file_handle) - { - bool result=true; -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- write left node (if it is available) - if(m_l_node!=NULL) - { - FileWriteInteger(file_handle,'L',SHORT_VALUE); - result&=m_l_node.SaveNode(file_handle); - } - else - FileWriteInteger(file_handle,'X',SHORT_VALUE); -//--- write data of current node - result&=Save(file_handle); -//--- write right node (if it is available) - if(m_r_node!=NULL) - { - FileWriteInteger(file_handle,'R',SHORT_VALUE); - result&=m_r_node.SaveNode(file_handle); - } - else - FileWriteInteger(file_handle,'X',SHORT_VALUE); -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Reading node data from file | -//+------------------------------------------------------------------+ -bool CTreeNode::LoadNode(const int file_handle,CTreeNode *main) - { - bool result=true; - short s_val; - CTreeNode *node; -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- read directions - s_val=(short)FileReadInteger(file_handle,SHORT_VALUE); - if(s_val=='L') - { - //--- read left node (if there is data) - node=CreateSample(); - if(node==NULL) - return(false); - m_l_node=node; - node.Parent(main); - result&=node.LoadNode(file_handle,node); - } -//--- read data of current node - result&=Load(file_handle); -//--- read directions - s_val=(short)FileReadInteger(file_handle,SHORT_VALUE); - if(s_val=='R') - { - //--- read right node (if there is data) - node=CreateSample(); - if(node==NULL) - return(false); - m_r_node=node; - node.Parent(main); - result&=node.LoadNode(file_handle,node); - } -//--- result - return(result); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/Canvas.mqh b/Include/Canvas/Canvas.mqh deleted file mode 100644 index 75b7a34..0000000 --- a/Include/Canvas/Canvas.mqh +++ /dev/null @@ -1,4846 +0,0 @@ -//+------------------------------------------------------------------+ -//| Canvas.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -#include - -#define SIGN(i) ((i<0) ? -1 : 1) - -//+------------------------------------------------------------------+ -//| Macro to generate color | -//+------------------------------------------------------------------+ -#define XRGB(r,g,b) (0xFF000000|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b)) -#define ARGB(a,r,g,b) ((uchar(a)<<24)|(uchar(r)<<16)|(uchar(g)<<8)|uchar(b)) -#define TRGB(a,rgb) ((uchar(a)<<24)|(rgb)) -#define GETRGB(clr) ((clr)&0xFFFFFF) -#define GETRGBA(clr) uchar((clr)>>24) -#define GETRGBR(clr) uchar((clr)>>16) -#define GETRGBG(clr) uchar((clr)>>8) -#define GETRGBB(clr) uchar(clr) -#define COLOR2RGB(clr) (0xFF000000|(uchar(clr)<<16)|(uchar((clr)>>8)<<8)|uchar((clr)>>16)) -#define RGB2COLOR(rgb) ((uchar(rgb)<<16)|(uchar((rgb)>>8)<<8)|uchar((rgb)>>16)) - -//+------------------------------------------------------------------+ -//| Line end style (round, butt, square) | -//+------------------------------------------------------------------+ -enum ENUM_LINE_END - { - LINE_END_ROUND, - LINE_END_BUTT, - LINE_END_SQUARE, - }; - -//+------------------------------------------------------------------+ -//| Class CCanvas | -//| Usage: class for working with a dynamic resource | -//+------------------------------------------------------------------+ -class CCanvas - { -private: - uint m_style; // line style template - uint m_style_idx; // variable - current index of bit in line style template - static uint m_default_colors[9]; // default colors - -protected: - long m_chart_id; // chart ID - string m_objname; // object name - ENUM_OBJECT m_objtype; // object type - string m_rcname; // resource name - int m_width; // canvas width - int m_height; // canvas height - ENUM_COLOR_FORMAT m_format; // method of color processing - //--- for text - string m_fontname; // font name - int m_fontsize; // font size - uint m_fontflags; // font flags - uint m_fontangle; // angle of text tilt to the X axis in 0.1 degrees - //--- data - uint m_pixels[]; // array of pixels - -public: - CCanvas(void); - ~CCanvas(void); - //--- create/attach/destroy - virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - bool CreateBitmap(const string name,const datetime time,const double price, - const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - bool CreateBitmap(const long chart_id,const int subwin,const string name, - const datetime time,const double price,const int width,const int height, - ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - bool CreateBitmapLabel(const string name,const int x,const int y, - const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - bool CreateBitmapLabel(const long chart_id,const int subwin,const string name, - const int x,const int y,const int width,const int height, - ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - virtual bool Attach(const long chart_id,const string objname,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - virtual bool Attach(const long chart_id,const string objname,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - virtual void Destroy(void); - //--- properties - string ChartObjectName(void) const { return(m_objname); } - string ResourceName(void) const { return(m_rcname); } - int Width(void) const { return(m_width); } - int Height(void) const { return(m_height); } - //--- update object on screen - void Update(const bool redraw=true); - bool Resize(const int width,const int height); - //--- clear/fill color - void Erase(const uint clr=0); - //--- data access - uint PixelGet(const int x,const int y) const; - void PixelSet(const int x,const int y,const uint clr); - //--- draw primitives - void LineVertical(int x,int y1,int y2,const uint clr); - void LineHorizontal(int x1,int x2,int y,const uint clr); - void Line(int x1,int y1,int x2,int y2,const uint clr); - void Polyline(int &x[],int &y[],const uint clr); - void Polygon(int &x[],int &y[],const uint clr); - void Rectangle(int x1,int y1,int x2,int y2,const uint clr); - void Triangle(int x1,int y1,int x2,int y2,int x3,int y3,const uint clr); - void Circle(int x,int y,int r,const uint clr); - void Ellipse(int x1,int y1,int x2,int y2,const uint clr); - void Arc(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,const uint clr); - void Arc(int x,int y,int rx,int ry,double fi3,double fi4,const uint clr); - void Arc(int x,int y,int rx,int ry,double fi3,double fi4,int &x3,int &y3,int &x4,int &y4,const uint clr); - void Pie(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,const uint clr,const uint fill_clr); - void Pie(int x,int y,int rx,int ry,double fi3,double fi4,const uint clr,const uint fill_clr); - //--- draw filled primitives - void FillRectangle(int x1,int y1,int x2,int y2,const uint clr); - void FillTriangle(int x1,int y1,int x2,int y2,int x3,int y3,const uint clr); - void FillPolygon(int &x[],int &y[],const uint clr); - void FillCircle(int x,int y,int r,const uint clr); - void FillEllipse(int x1,int y1,int x2,int y2,const uint clr); - void Fill(int x,int y,const uint clr); - void Fill(int x,int y,const uint clr,const uint threshould); - //--- draw primitives with antialiasing - void PixelSetAA(const double x,const double y,const uint clr); - void LineAA(const int x1,const int y1,const int x2,const int y2,const uint clr,const uint style=UINT_MAX); - void PolylineAA(int &x[],int &y[],const uint clr,const uint style=UINT_MAX); - void PolygonAA(int &x[],int &y[],const uint clr,const uint style=UINT_MAX); - void TriangleAA(const int x1,const int y1,const int x2,const int y2,const int x3,const int y3, - const uint clr,const uint style=UINT_MAX); - void CircleAA(const int x,const int y,const double r,const uint clr,const uint style=UINT_MAX); - void EllipseAA(const double x1,const double y1,const double x2,const double y2,const uint clr,const uint style=UINT_MAX); - //--- draw primitives with antialiasing by Wu's algorithm - void LineWu(int x1,int y1,int x2,int y2,const uint clr,const uint style=UINT_MAX); - void PolylineWu(const int &x[],const int &y[],const uint clr,const uint style=UINT_MAX); - void PolygonWu(const int &x[],const int &y[],const uint clr,const uint style=UINT_MAX); - void TriangleWu(const int x1,const int y1,const int x2,const int y2,const int x3,const int y3,const uint clr,const uint style=UINT_MAX); - void CircleWu(const int x,const int y,const double r,const uint clr,const uint style=UINT_MAX); - void EllipseWu(const int x1,const int y1,const int x2,const int y2,const uint clr,const uint style=UINT_MAX); - //--- draw primitives with prefiltered antialiasing - void LineThickVertical(const int x,const int y1,const int y2,const uint clr,const int size,const uint style,ENUM_LINE_END end_style); - void LineThickHorizontal(const int x1,const int x2,const int y,const uint clr,const int size,const uint style,ENUM_LINE_END end_style); - void LineThick(const int x1,const int y1,const int x2,const int y2,const uint clr,const int size,const uint style,ENUM_LINE_END end_style); - void PolylineThick(const int &x[],const int &y[],const uint clr,const int size,const uint style,ENUM_LINE_END end_style); - void PolygonThick(const int &x[],const int &y[],const uint clr,const int size,const uint style,ENUM_LINE_END end_style); - //--- draw primitives smoothing polyline and polygon - void PolylineSmooth(const int &x[],const int &y[],const uint clr,const int size, - ENUM_LINE_STYLE style=STYLE_SOLID,ENUM_LINE_END end_style=LINE_END_ROUND, - double tension=0.5,double step=10); - void PolygonSmooth(int &x[],int &y[],const uint clr,const int size, - ENUM_LINE_STYLE style=STYLE_SOLID,ENUM_LINE_END end_style=LINE_END_ROUND, - double tension=0.5,double step=10); - //--- for text - bool FontSet(const string name,const int size,const uint flags=0,const uint angle=0); - bool FontNameSet(string name); - bool FontSizeSet(int size); - bool FontFlagsSet(uint flags); - bool FontAngleSet(uint angle); - void FontGet(string &name,int &size,uint &flags,uint &angle); - string FontNameGet(void) const { return(m_fontname); } - int FontSizeGet(void) const { return(m_fontsize); } - uint FontFlagsGet(void) const { return(m_fontflags); } - uint FontAngleGet(void) const { return(m_fontangle); } - void TextOut(int x,int y,string text,const uint clr,uint alignment=0); - int TextWidth(const string text); - int TextHeight(const string text); - void TextSize(const string text,int &width,int &height); - //--- services - static uint GetDefaultColor(const int i); - void TransparentLevelSet(const uchar value); - //--- load bitmap from file - bool LoadFromFile(const string filename); - //--- line style property - uint LineStyleGet(void) const; - void LineStyleSet(const uint style); - //--- load bitmap from file to buffer - static bool LoadBitmap(const string filename,uint &data[],int &width,int &height); - -private: - bool FontSet(void); - void TextOutFast(int x,int y,string text,const uint clr,uint alignment=0); - bool PixelsSimilar(const uint clr0,const uint clr1,const uint threshould); - //--- for Wu's algorithm - void PixelTransform(const int x,const int y,const uint clr,const double alpha); - //--- for circle and ellipse - void PixelTransform4(const int x,const int y,const int dx,const int dy,const uint clr,const double alpha); - void PixelSet4AA(const double x,const double y,const double dx,const double dy,const uint clr); - //--- for thick line - void SegmentVertical(const int x,const int y1,const int y2,const int ysign,const double r,const uint clr,ENUM_LINE_END end_style); - void SegmentHorizontal(const int x1,const int x2,const int y,const int xsign,const double r,const uint clr,ENUM_LINE_END end_style); - void Segment(const int x1,const int y1,const int x2,const int y2,const double kp0,const double kp1,const int xsign,const int ysign, - const double rcos_k,const double rsin_k,const double r,const uint clr,ENUM_LINE_END end_style); - double DistancePointSegment(const double px,const double py,const double x1,const double y1,const double x2,const double y2); - //--- for pie - double AngleCalc(int x1,int y1,int x2,int y2); - //--- for polygon - int PointClassify(const CPoint &p0,const CPoint &p1,const CPoint &p2); - int PolygonClassify(const CPoint &p[]); - bool IsPolygonConvex(CPoint &p[]); - void PolygonNormalize(CPoint &p[]); - void PolygonIntersect(CPoint &p[],CPoint &add[]); - void PolygonFill(CPoint &p[],const uint clr); - //--- for smoothing polyline and polygon - void CalcCurveBezierEndp(const double xend,const double yend,const double xadj,const double yadj,const double tension,double &x,double &y); - void CalcCurveBezier(const int &x[],const int &y[],const int i,const double tension,double &x1,double &y1,double &x2,double &y2); - double CalcBezierX(const double t,const double x0,const double x1,const double x2,const double x3); - double CalcBezierY(const double t,const double y0,const double y1,const double y2,const double y3); - -protected: - //--- method for prefiltered antialiasing - virtual double FilterFunction(const double x); - }; -//+------------------------------------------------------------------+ -//| Initialize static array | -//+------------------------------------------------------------------+ -uint CCanvas::m_default_colors[9]= - { - XRGB(0,0,255), // blue - XRGB(255,0,0), // red - XRGB(0,128,0), // green - XRGB(255,242,0), // yellow - XRGB(255,0,128), // pink - XRGB(0,255,0), // lime - XRGB(185,0,61), // crimson - XRGB(0,183,239), // sky blue - XRGB(255,128,0) // orange - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CCanvas::CCanvas(void) : m_chart_id(0), - m_objname(NULL), - m_objtype(WRONG_VALUE), - m_rcname(NULL), - m_width(0), - m_height(0), - m_format(COLOR_FORMAT_XRGB_NOALPHA), - m_fontname("arial"), - m_fontsize(-120), - m_fontflags(0), - m_fontangle(0), - m_style(UINT_MAX), - m_style_idx(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CCanvas::~CCanvas(void) - { - } -//+------------------------------------------------------------------+ -//| Create dynamic resource | -//+------------------------------------------------------------------+ -bool CCanvas::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { - Destroy(); -//--- prepare data array - if(width>0 && height>0 && ArrayResize(m_pixels,width*height)>0) - { - //--- generate resource name - m_rcname="::"+name+(string)ChartID()+(string)(GetTickCount()+MathRand()); - //--- initialize data with zeros - ArrayInitialize(m_pixels,0); - //--- create dynamic resource - if(ResourceCreate(m_rcname,m_pixels,width,height,0,0,0,clrfmt)) - { - //--- successfully created - //--- complete initialization - m_width =width; - m_height=height; - m_format=clrfmt; - //--- succeed - return(true); - } - } -//--- error - destroy object - Destroy(); - return(false); - } -//+------------------------------------------------------------------+ -//| Create object on chart with attached dynamic resource | -//+------------------------------------------------------------------+ -bool CCanvas::CreateBitmap(const string name,const datetime time,const double price, - const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { - return(CreateBitmap(0,0,name,time,price,width,height,clrfmt)); - } -//+------------------------------------------------------------------+ -//| Create object on chart with attached dynamic resource | -//+------------------------------------------------------------------+ -bool CCanvas::CreateBitmap(const long chart_id,const int subwin,const string name, - const datetime time,const double price,const int width,const int height, - ENUM_COLOR_FORMAT clrfmt) - { -//--- create canvas - if(Create(name,width,height,clrfmt)) - { - //--- create attached object - if(ObjectCreate(chart_id,name,OBJ_BITMAP,subwin,time,price)) - { - //--- bind object with resource - if(ObjectSetString(chart_id,name,OBJPROP_BMPFILE,m_rcname)) - { - //--- successfully created - //--- complete initialization - m_chart_id=chart_id; - m_objname =name; - m_objtype =OBJ_BITMAP; - //--- succeed - return(true); - } - } - } -//--- error - return(false); - } -//+------------------------------------------------------------------+ -//| Create object on chart with attached dynamic resource | -//+------------------------------------------------------------------+ -bool CCanvas::CreateBitmapLabel(const string name,const int x,const int y, - const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { - return(CreateBitmapLabel(0,0,name,x,y,width,height,clrfmt)); - } -//+------------------------------------------------------------------+ -//| Create object on chart with attached dynamic resource | -//+------------------------------------------------------------------+ -bool CCanvas::CreateBitmapLabel(const long chart_id,const int subwin,const string name, - const int x,const int y,const int width,const int height, - ENUM_COLOR_FORMAT clrfmt) - { -//--- create canvas - if(Create(name,width,height,clrfmt)) - { - //--- create attached object - if(ObjectCreate(chart_id,name,OBJ_BITMAP_LABEL,subwin,0,0)) - { - //--- set x,y and bind object with resource - if(ObjectSetInteger(chart_id,name,OBJPROP_XDISTANCE,x) && - ObjectSetInteger(chart_id,name,OBJPROP_YDISTANCE,y) && - ObjectSetString(chart_id,name,OBJPROP_BMPFILE,m_rcname)) - { - //--- successfully created - //--- complete initialization - m_chart_id=chart_id; - m_objname =name; - m_objtype =OBJ_BITMAP_LABEL; - //--- succeed - return(true); - } - } - } -//--- error - return(false); - } -//+------------------------------------------------------------------+ -//| Attach new object with bitmap resource | -//+------------------------------------------------------------------+ -bool CCanvas::Attach(const long chart_id,const string objname,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA) - { - if(OBJ_BITMAP_LABEL==ObjectGetInteger(chart_id,objname,OBJPROP_TYPE)) - { - string rcname=ObjectGetString(chart_id,objname,OBJPROP_BMPFILE); - rcname=StringSubstr(rcname,StringFind(rcname,"::")); - if(ResourceReadImage(rcname,m_pixels,m_width,m_height)) - { - m_chart_id=chart_id; - m_objname=objname; - m_rcname=rcname; - m_format=clrfmt; - m_objtype=OBJ_BITMAP_LABEL; - //--- success - return(true); - } - } -//--- failed - return(false); - } -//+------------------------------------------------------------------+ -//| Attach new object without bitmap resource | -//+------------------------------------------------------------------+ -bool CCanvas::Attach(const long chart_id,const string objname,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA) - { - if(OBJ_BITMAP_LABEL==ObjectGetInteger(chart_id,objname,OBJPROP_TYPE)) - { - string rcname=ObjectGetString(chart_id,objname,OBJPROP_BMPFILE); - if(StringLen(rcname)==0 && width>0 && height>0 && ArrayResize(m_pixels,width*height)>0) - { - ZeroMemory(m_pixels); - if(ResourceCreate("::"+objname,m_pixels,width,height,0,0,0,clrfmt) && - ObjectSetString(chart_id,objname,OBJPROP_BMPFILE,"::"+objname)) - { - m_chart_id=chart_id; - m_width=width; - m_height=height; - m_objname=objname; - m_rcname="::"+objname; - m_format=clrfmt; - m_objtype=OBJ_BITMAP_LABEL; - //--- success - return(true); - } - } - } -//--- failed - return(false); - } -//+------------------------------------------------------------------+ -//| Remove object from chart and deallocate data array | -//+------------------------------------------------------------------+ -void CCanvas::Destroy(void) - { -//--- delete object - if(m_objname!=NULL) - { - ObjectDelete(m_chart_id,m_objname); - m_chart_id=0; - m_objname =NULL; - m_objtype =WRONG_VALUE; - } -//--- deallocate array - ArrayFree(m_pixels); -//--- free resource - if(m_rcname!=NULL) - { - ResourceFree(m_rcname); - m_rcname=NULL; - } -//--- zeroize data - m_width =0; - m_height=0; - } -//+------------------------------------------------------------------+ -//| Update object on screen (redraw) | -//+------------------------------------------------------------------+ -void CCanvas::Update(const bool redraw) - { -//--- check - if(m_rcname==NULL) - return; -//--- update resource and redraw - if(ResourceCreate(m_rcname,m_pixels,m_width,m_height,0,0,0,m_format) && redraw) - ChartRedraw(this.m_chart_id); - } -//+------------------------------------------------------------------+ -//| Resize | -//+------------------------------------------------------------------+ -bool CCanvas::Resize(const int width,const int height) - { -//--- check - if(m_rcname!=NULL && width>0 && height>0) - if(ArrayResize(m_pixels,width*height)>0) - { - m_width =width; - m_height=height; - //--- initialize data with zeros - ArrayInitialize(m_pixels,0); - //--- create dynamic resource - if(ResourceCreate(m_rcname,m_pixels,m_width,m_height,0,0,0,m_format)) - { - //--- bind object with resource - if(m_objname!=NULL && ObjectSetString(m_chart_id,m_objname,OBJPROP_BMPFILE,m_rcname)) - return(true); - } - } -//--- error - return(false); - } -//+------------------------------------------------------------------+ -//| Clear/Fill color | -//+------------------------------------------------------------------+ -void CCanvas::Erase(const uint clr) - { - ArrayInitialize(m_pixels,clr); - } -//+------------------------------------------------------------------+ -//| Get pixel color | -//+------------------------------------------------------------------+ -uint CCanvas::PixelGet(const int x,const int y) const - { -//--- check coordinates - if(x>=0 && x=0 && y=0 && x=0 && y=m_width || y<0 || y>=m_height) - return; -//--- - int index=y*m_width+x; - uint old_clr=m_pixels[index]; -//--- check if replacement is necessary - if(old_clr==clr) - return; -//--- use pseudo stack to emulate deeply-nested recursive calls - int stack[]; - uint count=1; - int idx; - int total=ArraySize(m_pixels); -//--- allocate memory for stack - if(ArrayResize(stack,total)==-1) - return; - stack[0]=index; - m_pixels[index]=clr; - for(uint i=0; i0 && m_pixels[idx]==old_clr) - { - m_pixels[idx]=clr; - stack[count++]=idx; - } - //--- top adjacent point - idx=index-m_width; - if(idx>=0 && m_pixels[idx]==old_clr) - { - m_pixels[idx]=clr; - stack[count++]=idx; - } - //--- right adjacent point - idx=index+1; - if(x=m_width || y<0 || y>=m_height || threshould>255) - return; -//--- - int index=y*m_width+x; - uint old_clr=m_pixels[index]; -//--- check if replacement is necessary - if(old_clr==clr) - return; -//--- use pseudo stack to emulate deeply-nested recursive calls - int stack[]; - uint count=1; - int idx; - int total=ArraySize(m_pixels); -//--- allocate memory for stack - if(ArrayResize(stack,total)==-1) - return; - stack[0]=index; - m_pixels[index]=clr; - for(uint i=0; i0 && PixelsSimilar(m_pixels[idx],old_clr,threshould) && m_pixels[idx]!=clr) - { - m_pixels[idx]=clr; - stack[count++]=idx; - } - //--- top adjacent point - idx=index-m_width; - if(idx>=0 && PixelsSimilar(m_pixels[idx],old_clr,threshould) && m_pixels[idx]!=clr) - { - m_pixels[idx]=clr; - stack[count++]=idx; - } - //--- right adjacent point - idx=index+1; - if(xy2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } -//--- line is out of image boundaries - if(y2<0 || y1>=m_height || x<0 || x>=m_width) - return; -//--- stay withing image boundaries - if(y1<0) - y1=0; - if(y2>=m_height) - y2=m_height-1; -//--- draw line - int index=y1*m_width+x; - for(int i=y1; i<=y2; i++,index+=m_width) - m_pixels[index]=clr; - } -//+------------------------------------------------------------------+ -//| Draw horizontal line | -//+------------------------------------------------------------------+ -void CCanvas::LineHorizontal(int x1,int x2,int y,const uint clr) - { - int tmp; -//--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } -//--- line is out of image boundaries - if(x2<0 || x1>=m_width || y<0 || y>=m_height) - return; -//--- stay withing image boundaries - if(x1<0) - x1=0; - if(x2>=m_width) - x2=m_width-1; -//--- draw line - ArrayFill(m_pixels,y*m_width+x1,(x2-x1)+1,clr); - } -//+------------------------------------------------------------------+ -//| Draw line according to Bresenham's algorithm | -//+------------------------------------------------------------------+ -void CCanvas::Line(int x1,int y1,int x2,int y2,const uint clr) - { -//--- line is out of image boundaries - if((x1<0 && x2<0) || (y1<0 && y2<0)) - return; - if(x1>=m_width && x2>=m_width) - return; - if(y1>=m_height && y2>=m_height) - return; -//--- get length by X and Y - int dx=(x2>x1)? x2-x1 : x1-x2; - int dy=(y2>y1)? y2-y1 : y1-y2; - if(dx==0) - { - //--- vertical line - LineVertical(x1,y1,y2,clr); - return; - } - if(dy==0) - { - //--- horizontal line - LineHorizontal(x1,x2,y1,clr); - return; - } -//--- get direction by X and Y - int sx=(x1=m_width || - y1<0 || y1>=m_height) - { - if(draw) - return; - } - else - { - //--- draw pixel - m_pixels[y1*m_width+x1]=clr; - draw=true; - } - //--- get coordinates of next pixel - int er2=er<<1; - if(er2>-dy) - { - er-=dy; - x1+=sx; - } - if(er2ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; - total--; -//--- draw - for(int i=0; iArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; - total--; -//--- draw - for(int i=0; i=dx) - { - xx=x+dx; - if(xx>=0 && xx=0 && yy=0 && yy=0 && xx=0 && yy=0 && yy=0 && xx=0 && yy=0 && yy=0 && xx=0 && yy=0 && yy=0) - { - dy--; - dd_y+=2; - f+=dd_y; - } - dx++; - dd_x+=2; - f+=dd_x; - } - } -//+------------------------------------------------------------------+ -//| Draw ellipse according to Bresenham's algorithm | -//+------------------------------------------------------------------+ -void CCanvas::Ellipse(int x1,int y1,int x2,int y2,const uint clr) - { - int x,y; - int rx,ry; - int dx,dy; - int xx,yy; - int rx_sq,ry_sq; - int f; - int tmp; -//--- handle extreme conditions - if(x1==x2) - { - if(y1==y2) - PixelSet(x1,y1,clr); - else - LineVertical(x1,y1,y2,clr); - return; - } - if(y1==y2) - { - LineHorizontal(x1,x2,y1,clr); - return; - } -//--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } -//--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - x =(x2+x1)>>1; - y =(y2+y1)>>1; - rx=(x2-x1)>>1; - ry=(y2-y1)>>1; - dx=0; - dy=ry; - rx_sq=rx*rx; - ry_sq=ry*ry; - f=(rx_sq<<1)*((dy-1)*dy)+rx_sq+(ry_sq<<1)*(1-rx_sq); - while(rx_sq*dy>ry_sq*dx) - { - yy=y+dy; - if(yy>=0 && yy=0 && xx=0 && xx=0 && yy=0 && xx=0 && xx=0) - { - dy--; - f-=(rx_sq<<2)*dy; - } - f+=(ry_sq<<1)*(3+(dx<<1)); - dx++; - } - f=(ry_sq<<1)*(dx+1)*dx+(rx_sq<<1)*(dy*(dy-2)+1)+(1-(rx_sq<<1))*ry_sq; - while(dy>=0) - { - yy=y+dy; - if(yy>=0 && yy=0 && xx=0 && xx=0 && yy=0 && xx=0 && xxx2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } -//--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - x =(x2+x1)>>1; - y =(y2+y1)>>1; -//--- check rays - if(x3==x && y3==y) - return; - if(x4==x && y4==y) - return; -//--- calculate parameters of ray x3,y3 - fi3=AngleCalc(x,y,x3,y3); -//--- calculate parameters of ray x4,y4 - fi4=AngleCalc(x,y,x4,y4); -//--- draw arc - Arc(x,y,x2-x,y2-y,fi3,fi4,clr); - } -//+------------------------------------------------------------------+ -//| Draws ellipse arc | -//+------------------------------------------------------------------+ -void CCanvas::Arc(int x,int y,int rx,int ry,double fi3,double fi4,const uint clr) - { - int x3,y3,x4,y4; -//--- check - if(rx<10 || ry<10) - return; - if(rx<0) - rx=-rx; - if(ry<0) - ry=-ry; -//--- check rays - if(fi3==fi4) - return; -//--- adjustment for passing through 0 - if(fi40) || // ray 3 is in the 1st or 2nd quadrant - (fi0) || // ray 4 is in the 1st or 2nd quadrant - (fi4-fi3>=M_PI)) // arc will pass through the top of the ellipse - { - dx=0; - dy=ry; - f=(rx_sq<<1)*((dy-1)*dy)+rx_sq+(ry_sq<<1)*(1-rx_sq); - while(rx_sq*dy>=ry_sq*dx) - { - yy=y-dy; - if(dx==0) - { - //--- central point - fi=AngleCalc(0,0,0,-dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(x,yy,clr); - ckw=ackw=true; - } - else - ckw=ackw=false; - xx_c=x; - yy_c=yy; - fi_c=fi; - xx_a=x; - yy_a=yy; - fi_a=fi; - } - else - { - //--- iterate clockwise - xx=x+dx; - fi=AngleCalc(0,0,dx,-dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 4 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 4 - if(!ckw) - { - ckw=true; - if(!ray4) - { - if(MathAbs(fi_c-MathMod(fi4,2*M_PI))MathAbs(fi-fi3)) - PixelSet(x3=xx,y3=yy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - ray3=true; - } - ckw=false; - } - //--- save parameters of the last iteration - xx_c=xx; - yy_c=yy; - fi_c=fi; - //--- iterate counterclockwise - xx=x-dx; - fi=AngleCalc(0,0,-dx,-dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 3 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 3 - if(!ackw) - { - ackw=true; - if(!ray3) - { - if(MathAbs(fi_a-fi3)MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=xx,y4=yy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - ray4=true; - } - ackw=false; - } - //--- save parameters of the last iteration - xx_a=xx; - yy_a=yy; - fi_a=fi; - } - //--- calculate coordinates of the next point - if(f>=0) - { - dy--; - f-=(rx_sq<<2)*dy; - } - f+=(ry_sq<<1)*(3+(dx<<1)); - dx++; - } - //--- if arc has been drawn clockwise "to the end" and ray 3 had not been found - if(ckw && !ray3) - { - fi=AngleCalc(0,0,dx,-dy); - if(MathAbs(fi_c-fi3)>MathAbs(fi-fi3)) - PixelSet(x3=x+dx,y3=y-dy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - } - //--- if arc has been drawn counterclockwise "to the end" and ray 4 had not been found - if(ackw && !ray4) - { - fi=AngleCalc(0,0,-dx,-dy); - if(MathAbs(fi_a-MathMod(fi4,2*M_PI))>MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=x-dx,y4=y-dy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - } - } -//--- 2 left -//--- -//--- if arc is obviously not within the rays range, don't draw - fi=MathMod(fi4,2*M_PI); - if((fi3>M_PI_2 && fi3<3*M_PI_2) || // ray 3 is in the 2nd or 3rd quadrant - (fi>M_PI_2 && fi<3*M_PI_2) || // ray 4 is in the 2nd or 3rd quadrant - (fi4-fi3>=M_PI)) // arc will pass through the left part of the ellipse - { - dx=rx; - dy=0; - f=(ry_sq<<1)*((dx-1)*dx)+ry_sq+(rx_sq<<1)*(1-ry_sq); - while(ry_sq*dx>=rx_sq*dy) - { - xx=x-dx; - if(dy==0) - { - //--- central point - fi=AngleCalc(0,0,-dx,0); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,y,clr); - ckw=ackw=true; - } - else - ckw=ackw=false; - xx_c=xx; - yy_c=y; - fi_c=fi; - xx_a=xx; - yy_a=y; - fi_a=fi; - } - else - { - //--- iterate clockwise - yy=y-dy; - fi=AngleCalc(0,0,-dx,-dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 4 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 4 - if(!ckw) - { - ckw=true; - if(!ray4) - { - if(MathAbs(fi_c-MathMod(fi4,2*M_PI))MathAbs(fi-fi3)) - PixelSet(x3=xx,y3=yy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - ray3=true; - } - ckw=false; - } - //--- save parameters of the last iteration - xx_c=xx; - yy_c=yy; - fi_c=fi; - //--- iterate counterclockwise - yy=y+dy; - fi=AngleCalc(0,0,-dx,dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 3 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 3 - if(!ackw) - { - ackw=true; - if(!ray3) - { - if(MathAbs(fi_a-fi3)MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=xx,y4=yy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - ray4=true; - } - ackw=false; - } - //--- save parameters of the last iteration - xx_a=xx; - yy_a=yy; - fi_a=fi; - } - //--- calculate coordinates of the next point - if(f>=0) - { - dx--; - f-=(ry_sq<<2)*dx; - } - f+=(rx_sq<<1)*(3+(dy<<1)); - dy++; - } - //--- if arc has been drawn clockwise "to the end" and ray 3 had not been found - if(ckw && !ray3) - { - fi=AngleCalc(0,0,-dx,-dy); - if(MathAbs(fi_c-fi3)>MathAbs(fi-fi3)) - PixelSet(x3=x-dx,y3=y-dy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - } - //--- if arc has been drawn counterclockwise "to the end" and ray 4 had not been found - if(ackw && !ray4) - { - fi=AngleCalc(0,0,-dx,dy); - if(MathAbs(fi_a-MathMod(fi4,2*M_PI))>MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=x-dx,y4=y+dy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - } - } -//--- 3 bottom -//--- -//--- if arc is obviously not within the rays range, don't draw - fi=MathMod(fi4,2*M_PI); - if((fi3>M_PI && fi3<2*M_PI) || // ray 3 is in the 3rd or 4th quadrant - (fi>M_PI && fi<2*M_PI) || // ray 4 is in the 3rd or 4th quadrant - (fi4-fi3>=M_PI)) // arc will pass through the bottom of the ellipse - { - dx=0; - dy=ry; - f=(rx_sq<<1)*((dy-1)*dy)+rx_sq+(ry_sq<<1)*(1-rx_sq); - while(rx_sq*dy>=ry_sq*dx) - { - yy=y+dy; - if(dx==0) - { - //--- central point - fi=AngleCalc(0,0,0,dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(x,yy,clr); - ckw=ackw=true; - } - else - ckw=ackw=false; - xx_c=x; - yy_c=yy; - fi_c=fi; - xx_a=x; - yy_a=yy; - fi_a=fi; - } - else - { - //--- iterate clockwise - xx=x-dx; - fi=AngleCalc(0,0,-dx,dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 4 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 4 - if(!ckw) - { - ckw=true; - if(!ray4) - { - if(MathAbs(fi_c-MathMod(fi4,2*M_PI))MathAbs(fi-fi3)) - PixelSet(x3=xx,y3=yy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - ray3=true; - } - ckw=false; - } - //--- save parameters of the last iteration - xx_c=xx; - yy_c=yy; - fi_c=fi; - //--- iterate counterclockwise - xx=x+dx; - fi=AngleCalc(0,0,dx,dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 3 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 3 - if(!ackw) - { - ackw=true; - if(!ray3) - { - if(MathAbs(fi_a-fi3)MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=xx,y4=yy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - ray4=true; - } - ackw=false; - } - //--- save parameters of the last iteration - xx_a=xx; - yy_a=yy; - fi_a=fi; - } - //--- calculate coordinates of the next point - if(f>=0) - { - dy--; - f-=(rx_sq<<2)*dy; - } - f+=(ry_sq<<1)*(3+(dx<<1)); - dx++; - } - //--- if arc has been drawn clockwise "to the end" and ray 3 had not been found - if(ckw && !ray3) - { - fi=AngleCalc(0,0,-dx,dy); - if(MathAbs(fi_c-fi3)>MathAbs(fi-fi3)) - PixelSet(x3=x-dx,y3=y+dy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - } - //--- if arc has been drawn counterclockwise "to the end" and ray 4 had not been found - if(ackw && !ray4) - { - fi=AngleCalc(0,0,dx,dy); - if(MathAbs(fi_a-MathMod(fi4,2*M_PI))>MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=x+dx,y4=y+dy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - } - } -//--- 4 right -//--- -//--- if arc is obviously not within the rays range, don't draw - fi=MathMod(fi4,2*M_PI); - if((fi33*M_PI_2) || // ray 3 is 1 or 4 quadrant - (fi3*M_PI_2) || // ray 4 is 1 or 4 quadrant - (fi4-fi3>=M_PI)) // arc will pass through the right side of the ellipse - { - dx=rx; - dy=0; - f=(ry_sq<<1)*((dx-1)*dx)+ry_sq+(rx_sq<<1)*(1-ry_sq); - while(ry_sq*dx>=rx_sq*dy) - { - xx=x+dx; - if(dy==0) - { - //--- central point - fi=AngleCalc(0,0,dx,0); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,y,clr); - ckw=ackw=true; - } - else - ckw=ackw=false; - xx_c=xx; - yy_c=y; - fi_c=fi; - xx_a=xx; - yy_a=y; - fi_a=fi; - } - else - { - //--- iterate clockwise - yy=y+dy; - fi=AngleCalc(0,0,dx,dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 4 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 4 - if(!ckw) - { - ckw=true; - if(!ray4) - { - if(MathAbs(fi_c-MathMod(fi4,2*M_PI))MathAbs(fi-fi3)) - PixelSet(x3=xx,y3=yy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - ray3=true; - } - ckw=false; - } - //--- save parameters of the last iteration - xx_c=xx; - yy_c=yy; - fi_c=fi; - //--- iterate counterclockwise - yy=y-dy; - fi=AngleCalc(0,0,dx,-dy); - if((fi<=fi4 && fi3<=fi) || (fi4>=2*M_PI && fi<=fi4-2*M_PI)) - { - PixelSet(xx,yy,clr); - //--- if arc haven't been drawn before and intersection point of ray 3 and arc is not defined - //--- this means that we (while iterating over points of the ellipse) had just crossed ray 3 - if(!ackw) - { - ackw=true; - if(!ray3) - { - if(MathAbs(MathMod(fi_a,2*M_PI)-fi3)MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=xx,y4=yy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - ray4=true; - } - ackw=false; - } - //--- save parameters of the last iteration - xx_a=xx; - yy_a=yy; - fi_a=fi; - } - //--- calculate coordinates of the next point - if(f>=0) - { - dx--; - f-=(ry_sq<<2)*dx; - } - f+=(rx_sq<<1)*(3+(dy<<1)); - dy++; - } - //--- if arc has been drawn clockwise "to the end" and ray 3 had not been found - if(ckw && !ray3) - { - fi=AngleCalc(0,0,dx,dy); - if(MathAbs(fi_c-fi3)>MathAbs(fi-fi3)) - PixelSet(x3=x+dx,y3=y+dy,clr); - else - { - x3=xx_c; - y3=yy_c; - } - } - //--- if arc has been drawn counterclockwise "to the end" and ray 4 had not been found - if(ackw && !ray4) - { - fi=AngleCalc(0,0,dx,-dy); - if(MathAbs(MathMod(fi_a,2*M_PI)-MathMod(fi4,2*M_PI))>MathAbs(fi-MathMod(fi4,2*M_PI))) - PixelSet(x4=x+dx,y4=y-dy,clr); - else - { - x4=xx_a; - y4=yy_a; - } - } - } - } -//+------------------------------------------------------------------+ -//| Draws ellipse pie | -//+------------------------------------------------------------------+ -void CCanvas::Pie(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4,const uint clr,const uint fill_clr) - { - int tmp; - int x,y; -//--- - double fi3; - double fi4; -//--- check - if(x1==x2 || y1==y2) - return; -//--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } -//--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - x =(x2+x1)>>1; - y =(y2+y1)>>1; -//--- check rays - if(x3==x && y3==y) - return; - if(x4==x && y4==y) - return; -//--- calculate parameters of ray x3,y3 - fi3=AngleCalc(x,y,x3,y3); -//--- calculate parameters of ray x4,y4 - fi4=AngleCalc(x,y,x4,y4); -//--- draw pie - Pie(x,y,x2-x,y2-y,fi3,fi4,clr,fill_clr); - } -//+------------------------------------------------------------------+ -//| Draws ellipse pie | -//+------------------------------------------------------------------+ -void CCanvas::Pie(int x,int y,int rx,int ry,double fi3,double fi4,const uint clr,const uint fill_clr) - { - int x3=x; - int y3=y; - int x4=x; - int y4=y; -//--- check - if(rx==0 || ry==0) - return; - if(rx<0) - rx=-rx; - if(ry<0) - ry=-ry; -//--- check rays - if(fi3==fi4) - return; -//--- adjustment for passing through 0 - if(fi4ry) - rx=ry; - double fi=(fi3+fi4)/2; - int xf=x+(int)(0.9*rx*cos(fi)); - int yf=y-(int)(0.9*rx*sin(fi)); - Fill(xf,yf,fill_clr); - } -//+------------------------------------------------------------------+ -//| Draw filled circle | -//+------------------------------------------------------------------+ -void CCanvas::FillCircle(int x,int y,int r,const uint clr) - { - int f =1-r; - int dd_x=1; - int dd_y=-2*r; - int dx =0; - int dy =r; -//--- draw - while(dy>=dx) - { - LineHorizontal(x-dy,x+dy,y-dx,clr); - LineHorizontal(x-dy,x+dy,y+dx,clr); - //--- - if(f>=0) - { - LineHorizontal(x-dx,x+dx,y-dy,clr); - LineHorizontal(x-dx,x+dx,y+dy,clr); - dy--; - dd_y+=2; - f+=dd_y; - } - dx++; - dd_x+=2; - f+=dd_x; - } - } -//+------------------------------------------------------------------+ -//| Draw filled ellipse | -//+------------------------------------------------------------------+ -void CCanvas::FillEllipse(int x1,int y1,int x2,int y2,const uint clr) - { - int x,y; - int rx,ry; - int dx,dy; - int rx_sq,ry_sq; - int f; - int tmp; -//--- handle extreme conditions - if(x1==x2) - { - if(y1==y2) - PixelSet(x1,y1,clr); - else - LineVertical(x1,y1,y2,clr); - return; - } - if(y1==y2) - { - LineHorizontal(x1,x2,y1,clr); - return; - } -//--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } -//--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - x =(x2+x1)>>1; - y =(y2+y1)>>1; - rx=(x2-x1)>>1; - ry=(y2-y1)>>1; - dx=0; - dy=ry; - rx_sq=rx*rx; - ry_sq=ry*ry; - f=(rx_sq<<1)*((dy-1)*dy)+rx_sq+(ry_sq<<1)*(1-rx_sq); - while(rx_sq*dy>ry_sq*(dx)) - { - LineHorizontal(x-dx,x+dx,y+dy,clr); - LineHorizontal(x-dx,x+dx,y-dy,clr); - if(f>=0) - { - dy--; - f-=(rx_sq<<2)*dy; - } - f+=(ry_sq<<1)*(3+(dx<<1)); - dx++; - } - f=(ry_sq<<1)*(dx+1)*dx+(rx_sq<<1)*(dy*(dy-2)+1)+(1-(rx_sq<<1))*ry_sq; - while(dy>=0) - { - LineHorizontal(x-dx,x+dx,y+dy,clr); - LineHorizontal(x-dx,x+dx,y-dy,clr); - if(f<=0) - { - dx++; - f+=(ry_sq<<2)*dx; - } - dy--; - f+=(rx_sq<<1)*(3-(dy<<1)); - } - } -//+------------------------------------------------------------------+ -//| Draw filled rectangle | -//+------------------------------------------------------------------+ -void CCanvas::FillRectangle(int x1,int y1,int x2,int y2,const uint clr) - { - int tmp; -//--- sort vertexes - if(x2=m_width || y1>=m_height) - return; -//--- stay withing screen boundaries - if(x1<0) - x1=0; - if(y1<0) - y1=0; - if(x2>=m_width) - x2=m_width -1; - if(y2>=m_height) - y2=m_height-1; - int len=(x2-x1)+1; -//--- set pixels - for(; y1<=y2; y1++) - ArrayFill(m_pixels,y1*m_width+x1,len,clr); - } -//+------------------------------------------------------------------+ -//| Draw filled triangle | -//+------------------------------------------------------------------+ -void CCanvas::FillTriangle(int x1,int y1,int x2,int y2,int x3,int y3,const uint clr) - { - int xx1,xx2,tmp; - double k1=0,k2=0,xd1,xd2; -//--- sort vertexes from lesser to greater - if(y1>y2) - { - tmp=y2; - y2 =y1; - y1 =tmp; - tmp=x2; - x2 =x1; - x1=tmp; - } - if(y1>y3) - { - tmp=y1; - y1 =y3; - y3 =tmp; - tmp=x1; - x1 =x3; - x3 =tmp; - } - if(y2>y3) - { - tmp=y2; - y2 =y3; - y3 =tmp; - tmp=x2; - x2 =x3; - x3 =tmp; - } -//--- all vertexes are out of image boundaries - if(y3<0 || y1>m_height) - return; - if(x1<0 && x2<0 && x3<0) - return; - if(x1>m_width && x2>m_width && x3>m_width) - return; -//--- find coefficients of lines - if((tmp=y1-y2)!=0) - k1=(x1-x2)/(double)tmp; - if((tmp=y1-y3)!=0) - k2=(x1-x3)/(double)tmp; -//--- - xd1=x1; - xd2=x1; -//--- - for(int i=y1; i<=y3; i++) - { - if(i==y2) - { - if((tmp=y2-y3)!=0) - k1=(x2-x3)/(double)tmp; - xd1=x2; - } - //--- calculate new boundaries of triangle line - xx1 =(int)xd1; - xd1+=k1; - xx2 =(int)xd2; - xd2+=k2; - //--- triangle line is out of screen boundaries - if(i<0 || i>=m_height) - continue; - //--- sort - if(xx1>xx2) - { - tmp=xx1; - xx1=xx2; - xx2=tmp; - } - //--- line is out of screen boundaries - if(xx2<0 || xx1>=m_width) - continue; - //--- draw only what is within screen boundaries - if(xx1<0) - xx1=0; - if(xx2>=m_width) - xx2=m_width-1; - //--- draw horizontal line of triangle - ArrayFill(m_pixels,i*m_width+xx1,xx2-xx1,clr); - } - } -//+------------------------------------------------------------------+ -//| Draw filled poligon | -//+------------------------------------------------------------------+ -void CCanvas::FillPolygon(int &x[],int &y[],const uint clr) - { - static CPoint p[]; - int total=ArraySize(x); - if(total>ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<3) - return; -//--- resize array of points - ArrayResize(p,total); -//--- find top-left point - int imin=0; - int xmin=x[0]; - int ymin=y[0]; - for(int i=1; iymin) - continue; - if(y[i]==ymin) - { - if(x[i]0.0) - xx[1]=xx[3]=ix+1; - if(dy<0.0) - yy[2]=yy[2]=iy-1; - if(dy==0.0) - yy[2]=yy[2]=iy; - if(dy>0.0) - yy[2]=yy[2]=iy+1; -//--- calculate radii and sum of their squares - for(int i=0; i<4; i++) - { - dx=xx[i]-x; - dy=yy[i]-y; - rr[i]=1/(dx*dx+dy*dy); - rrr+=rr[i]; - } -//--- draw pixels - for(int i=0; i<4; i++) - { - k=rr[i]/rrr; - c=PixelGet(xx[i],yy[i]); - a=(uchar)(k*GETRGBA(clr)+(1-k)*GETRGBA(c)); - r=(uchar)(k*GETRGBR(clr)+(1-k)*GETRGBR(c)); - g=(uchar)(k*GETRGBG(clr)+(1-k)*GETRGBG(c)); - b=(uchar)(k*GETRGBB(clr)+(1-k)*GETRGBB(c)); - PixelSet(xx[i],yy[i],ARGB(a,r,g,b)); - } - } -//+------------------------------------------------------------------+ -//| Get line style | -//+------------------------------------------------------------------+ -uint CCanvas::LineStyleGet(void) const - { - switch(m_style) - { - case 0xFFFFFF: - return(STYLE_SOLID); - break; - case 0x3FFFF: - return(STYLE_DASH); - break; - case 0x1C71C7: - return(STYLE_DOT); - break; - case 0x381FF: - return(STYLE_DASHDOT); - break; - case 0x1C71FF: - return(STYLE_DASHDOTDOT); - break; - default: - return (m_style); - break; - } - } -//+------------------------------------------------------------------+ -//| Set line style | -//+------------------------------------------------------------------+ -void CCanvas::LineStyleSet(const uint style) - { - switch(style) - { - case STYLE_SOLID: - m_style=0xFFFFFF; - break; - case STYLE_DASH: - m_style=0x3FFFF; - break; - case STYLE_DOT: - m_style=0x1C71C7; - break; - case STYLE_DASHDOT: - m_style=0x381FF; - break; - case STYLE_DASHDOTDOT: - m_style=0x1C71FF; - break; - default: - //--- high-order bit must be set then custom style - if((style&0x80000000)!=0) - { - m_style=style; - } - break; - } - m_style_idx=0; - } -//+------------------------------------------------------------------+ -//| Draw line with antialiasing (with style) | -//+------------------------------------------------------------------+ -void CCanvas::LineAA(const int x1,const int y1,const int x2,const int y2,const uint clr,const uint style) - { -//--- line is out of image boundaries - if((x1<0 && x2<0) || (y1<0 && y2<0)) - return; - if(x1>=m_width && x2>=m_width) - return; - if(y1>=m_height && y2>=m_height) - return; -//--- check - if(x1==x2 && y1==y2) - { - PixelSet(x1,y1,clr); - return; - } -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); -//--- preliminary calculations - double dx=x2-x1; - double dy=y2-y1; - double xy=sqrt(dx*dx+dy*dy); - double xx=x1; - double yy=y1; - uint mask=1<=fabs(dx) && fabs(y2-yy)>=fabs(dy)); -//--- set last pixel - if((m_style&mask)==mask) - { - PixelSetAA(x2,y2,clr); - } -//--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - } -//+------------------------------------------------------------------+ -//| Draw polyline with antialiasing (with style) | -//+------------------------------------------------------------------+ -void CCanvas::PolylineAA(int &x[],int &y[],const uint clr,const uint style) - { -//--- check arrays - int total=ArraySize(x); - if(total>ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; - total--; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<=m_width && x2>=m_width) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - if(y1>=m_height && y2>=m_height) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- check - if(x1==x2 && y1==y2) - { - PixelSet(x1,y1,clr); - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- preliminary calculations - double dx=x2-x1; - double dy=y2-y1; - double xy=sqrt(dx*dx+dy*dy); - double xx=x1; - double yy=y1; - //--- set pixels - dx/=xy; - dy/=xy; - do - { - if((m_style&mask)==mask) - { - PixelSetAA(xx,yy,clr); - } - xx+=dx; - yy+=dy; - mask<<=1; - if(mask==0x1000000) - mask=1; - } - while(fabs(x2-xx)>=fabs(dx) && fabs(y2-yy)>=fabs(dy)); - //--- set last pixel - if((m_style&mask)==mask) - { - PixelSetAA(x2,y2,clr); - } - mask<<=1; - if(mask==0x1000000) - mask=1; - } -//--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - } -//+------------------------------------------------------------------+ -//| Draw polygon with antialiasing (with style) | -//+------------------------------------------------------------------+ -void CCanvas::PolygonAA(int &x[],int &y[],const uint clr,const uint style) - { -//--- check arrays - int total=ArraySize(x); - if(total>ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<=m_width && x2>=m_width) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - if(y1>=m_height && y2>=m_height) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- check - if(x1==x2 && y1==y2) - { - PixelSet(x1,y1,clr); - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- preliminary calculations - double dx=x2-x1; - double dy=y2-y1; - double xy=sqrt(dx*dx+dy*dy); - double xx=x1; - double yy=y1; - //--- set pixels - dx/=xy; - dy/=xy; - do - { - if((m_style&mask)==mask) - { - PixelSetAA(xx,yy,clr); - } - xx+=dx; - yy+=dy; - mask<<=1; - if(mask==0x1000000) - mask=1; - } - while(fabs(x2-xx)>=fabs(dx) && fabs(y2-yy)>=fabs(dy)); - //--- set last pixel - if((m_style&mask)==mask) - { - PixelSetAA(x2,y2,clr); - } - } -//--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - } -//+------------------------------------------------------------------+ -//| Draw triangle with antialiasing | -//+------------------------------------------------------------------+ -void CCanvas::TriangleAA(const int x1,const int y1,const int x2,const int y2,const int x3,const int y3,const uint clr,const uint style) - { -//--- draw - int x[3]; - int y[3]; - x[0] = x1; - x[1] = x2; - x[2] = x3; - y[0] = y1; - y[1] = y2; - y[2] = y3; - PolygonAA(x,y,clr,style); - } -//+------------------------------------------------------------------+ -//| Draw circle with antialiasing | -//+------------------------------------------------------------------+ -void CCanvas::CircleAA(const int x,const int y,const double r,const uint clr,const uint style=UINT_MAX) - { - if(r<=0) - return; -//--- preliminary calculations - double xx=x+r; - double yy=y; - double fi=0; - double df=M_PI_2/MathCeil(r); -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<M_PI) - df/=2; - do - { - xx=x+r*cos(fi); - yy=y-r*sin(fi); - if((m_style&mask)==mask) - PixelSetAA(xx,yy,clr); - mask<<=1; - if(mask==0x1000000) - mask=1; - fi+=df; - } - while(fabs(2*M_PI-fi)>=df/2); -//--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - } -//+------------------------------------------------------------------+ -//| Draw ellipse with antialiasing | -//+------------------------------------------------------------------+ -void CCanvas::EllipseAA(const double x1,const double y1,const double x2,const double y2,const uint clr,const uint style=UINT_MAX) - { - double rx = (x2-x1)/2; - double ry = (y2-y1)/2; -//--- preliminary calculations - double x=(x2>x1) ? x1+rx : x2+rx; - double y=(y2>y1) ? y1+ry : y2+ry; - double rx2=rx*rx; - double ry2=ry*ry; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<ym) - continue; - if((p[i].y==ym) && (p[i].x>xm)) - continue; - im=i; - xm=p[i].x; - ym=p[i].y; - } -//--- check the orientation of triangle - return PointClassify(p[(im-1+total)%total],p[im],p[(im+1)%total]); - } -//+------------------------------------------------------------------+ -//| Checks convexity of polygon | -//+------------------------------------------------------------------+ -bool CCanvas::IsPolygonConvex(CPoint &p[]) - { - int total=ArraySize(p); -//--- triangle - always convex - if(total==3) - return(true); - int res=SIGN(PointClassify(p[0],p[1],p[2])); - for(int i=1; iymin) - continue; - if(p[i].y==ymin) - { - if(p[i].xp[il].y) - return; - if(yy!=p[il].y) - { - dl=(p[il].x-xl)/(p[il].y-yy); - //--- make adjustment for half of left increment dl/2 - LineHorizontal((int)MathCeil(xl+dl/2),(int)MathFloor(xl),yy,clr); - xl+=dl/2; - } - else - LineHorizontal((int)MathCeil(xl),(int)MathFloor(p[il].x),yy,clr); - } - while(yy==p[ir].y) - { - ir=(ir+1)%total; - if(yy>p[ir].y) - return; - if(yy!=p[ir].y) - { - dr=(p[ir].x-xr)/(p[ir].y-yy); - //--- make adjustment for half of right increment dr/2 - LineHorizontal((int)MathCeil(xr),(int)MathFloor(xr+dr/2),yy,clr); - xr+=dr/2; - } - else - LineHorizontal((int)MathCeil(p[ir].x),(int)MathFloor(xr),yy,clr); - } - yy++; - if(yy==p[il].y) - xl=p[il].x; - else - xl+=dl; - if(yy==p[ir].y) - xr=p[ir].x; - else - xr+=dr; - LineHorizontal((int)MathCeil(xl),(int)MathFloor(xr),yy,clr); - } - while(il>=ir && ir!=0); - } -//+------------------------------------------------------------------+ -//| Draw line according to Wu's algorithm | -//+------------------------------------------------------------------+ -void CCanvas::LineWu(int x1,int y1,int x2,int y2,const uint clr,const uint style=UINT_MAX) - { -//--- calculating the variation of the coordinates - int dx = (x2 > x1) ? (x2 - x1) : (x1 - x2); - int dy = (y2 > y1) ? (y2 - y1) : (y1 - y2); -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - //--- line is out of image boundaries - if(y2<0 || y1>=m_height || x1<0 || x1>=m_width) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- stay withing image boundaries - if(y1<0) - y1=0; - if(y2>=m_height-1) - y2=m_height-1; - //--- draw line - int index=y1*m_width+x1; - for(int i=y1; i<=y2; i++,index+=m_width) - { - if((m_style&mask)==mask) - m_pixels[index]=clr; - - mask<<=1; - if(mask==0x1000000) - mask=1; - } - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - //--- success - return; - } -//--- check if dy==0 then draw horizontal line - if(dy==0) - { - //--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } - //--- line is out of image boundaries - if(x2<0 || x1>=m_width || y1<0 || y1>=m_height) - { - //--- set the previous line style - if(style!=UINT_MAX) - m_style=prev_style; - return; - } - //--- stay withing image boundaries - if(x1<0) - x1=0; - if(x2>=m_width) - x2=m_width-1; - //--- draw line - for(int i=0,index=y1*m_width+x1; i 1) - else - { - //--- first point has to have a smaller Y coordinate - if(y2ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; - total--; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1< x1) ? (x2 - x1) : (x1 - x2); - int dy = (y2 > y1) ? (y2 - y1) : (y1 - y2); - int tmp; - //--- check if dx==0 then draw vertical line - if(dx==0) - { - //--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - //--- line is out of image boundaries - if(y2<0 || y1>=m_height || x1<0 || x1>=m_width) - continue; - //--- stay withing image boundaries - if(y1<0) - y1=0; - if(y2>=m_height-1) - y2=m_height-1; - //--- draw line - int index=y1*m_width+x1; - for(int j=y1; j<=y2; j++,index+=m_width) - { - if((m_style&mask)==mask) - m_pixels[index]=clr; - - mask<<=1; - if(mask==0x1000000) - mask=1; - } - continue; - } - //--- check if dy==0 then draw horizontal line - if(dy==0) - { - //--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } - //--- line is out of image boundaries - if(x2<0 || x1>=m_width || y1<0 || y1>=m_height) - continue; - //--- stay withing image boundaries - if(x1<0) - x1=0; - if(x2>=m_width) - x2=m_width-1; - //--- draw line - for(int j=0,index=y1*m_width+x1; j 1) - else - { - //--- first point has to have a smaller Y coordinate - if(y2ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1< x1) ? (x2 - x1) : (x1 - x2); - int dy = (y2 > y1) ? (y2 - y1) : (y1 - y2); - int tmp; - //--- check if dx==0 then draw vertical line - if(dx==0) - { - //--- sort by Y - if(y1>y2) - { - tmp=y1; - y1 =y2; - y2 =tmp; - } - //--- line is out of image boundaries - if(y2<0 || y1>=m_height || x1<0 || x1>=m_width) - continue; - //--- stay withing image boundaries - if(y1<0) - y1=0; - if(y2>=m_height-1) - y2=m_height-1; - //--- draw line - int index=y1*m_width+x1; - for(int j=y1; j<=y2; j++,index+=m_width) - { - if((m_style&mask)==mask) - m_pixels[index]=clr; - - mask<<=1; - if(mask==0x1000000) - mask=1; - } - continue; - } - //--- check if dy==0 then draw horizontal line - if(dy==0) - { - //--- sort by X - if(x1>x2) - { - tmp=x1; - x1 =x2; - x2 =tmp; - } - //--- line is out of image boundaries - if(x2<0 || x1>=m_width || y1<0 || y1>=m_height) - continue; - //--- stay withing image boundaries - if(x1<0) - x1=0; - if(x2>=m_width) - x2=m_width-1; - //--- draw line - for(int j=0,index=y1*m_width+x1; j 1) - else - { - //--- first point has to have a smaller Y coordinate - if(y2x1) ? x1+rx : x2+rx; - int y=(y2>y1) ? y1+ry : y2+ry; - if(rx<=0 || ry<=0) - return; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<0) - LineWu(x,y1,x,y2,clr,style); - return; - } -//--- r be the filter radius (and also the half-width of the wide line) - double r=(size/2.0); -//--- primary calculate - int dy=MathAbs(y2-y1); - int sign=(y10) - LineWu(x1,y,x2,y,clr,style); - return; - } -//--- r be the filter radius (and also the half-width of the wide line) - double r=(size/2.0); -//--- primary calculate - int dx=MathAbs(x2-x1); - int sign=(x10) - LineWu(x1,y1,x2,y2,clr,style); - return; - } -//--- r be the filter radius (and also the half-width of the wide line) - double r=(size/2.0); -//--- compute x and y deltas - double dx=MathAbs(x2-x1); - double dy=MathAbs(y2-y1); - if(dx==0) - { - LineThickVertical(x1,y1,y2,clr,size,style,end_style); - return; - } - if(dy==0) - { - LineThickHorizontal(x1,x2,y1,clr,size,style,end_style); - return; - } -//--- compute the linear coefficients of the two (scaled) edge functions - double k=MathArctan(dx/dy); - double rcos_k=r*cos(k); - double rsin_k=r*sin(k); -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<0) - PolylineWu(x,y,clr,style); - return; - } -//--- check arrays - int total=ArraySize(x); - if(total>ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; - total--; -//--- r be the filter radius (and also the half-width of the wide line) - double r=(size/2.0); -//--- - double gap=1.0; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<0) - PolylineWu(x,y,clr,style); - return; - } -//--- check arrays - int total=ArraySize(x); - if(total>ArraySize(y)) - total=ArraySize(y); -//--- check - if(total<2) - return; -//--- r be the filter radius (and also the half-width of the wide line) - double r=(size/2.0); -//--- - double gap=1.0; -//--- set the line style - uint prev_style=m_style; - if(style!=UINT_MAX) - LineStyleSet(style); - uint mask=1<>16) &0xff) - - uint((clr1>>16) &0xff)); - uint dg=MathAbs(uint((clr0>>8) &0xff) - - uint((clr1>>8) &0xff)); - uint db=MathAbs(uint((clr0>>0) &0xff) - - uint((clr1>>0) &0xff)); -//--- return - return (dr<=threshould || dg<=threshould || db<=threshould); - } -//+------------------------------------------------------------------+ -//| Calculate and set new color | -//+------------------------------------------------------------------+ -void CCanvas::PixelTransform(const int x,const int y,const uint clr,const double alpha) - { - int index=y*m_width+x; -//--- check - if(x<0 || y<0 || x>m_width || y>m_height || index>=ArraySize(m_pixels)) - return; -//--- check alpha - if(alpha==1) - { - m_pixels[index]=clr; - return; - } -//--- get pixel color - uint clr0=m_pixels[index]; -//--- transform of color component for the background - double r0 = ((clr0>>16) & 0xFF) * (1.0-alpha); - double g0 = ((clr0>>8) & 0xFF) * (1.0-alpha); - double b0 = ((clr0>>0) & 0xFF) * (1.0-alpha); -//--- transform of color component - double r1 = ((clr>>16) & 0xFF) * (alpha); - double g1 = ((clr>>8) & 0xFF) * (alpha); - double b1 = ((clr>>0) & 0xFF) * (alpha); -//--- components of the new color - int r = (int)(r0+r1); - int g = (int)(g0+g1); - int b = (int)(b0+b1); -//--- set new color - m_pixels[y*m_width+x]=((r<<16)|(g<<8)|(b<<0)|(255<<24)); - } -//+------------------------------------------------------------------+ -//| Draw 4 pixel with PixelTransform method | -//+------------------------------------------------------------------+ -void CCanvas::PixelTransform4(const int x,const int y,const int dx,const int dy,const uint clr,const double alpha) - { - PixelTransform(x+dx,y+dy,clr,alpha); - PixelTransform(x-dx,y+dy,clr,alpha); - PixelTransform(x+dx,y-dy,clr,alpha); - PixelTransform(x-dx,y-dy,clr,alpha); - } -//+------------------------------------------------------------------+ -//| Draw 4 pixel with antialiasing | -//+------------------------------------------------------------------+ -void CCanvas::PixelSet4AA(const double x,const double y,const double dx,const double dy,const uint clr) - { - PixelSetAA(x+dx,y+dy,clr); - PixelSetAA(x-dx,y+dy,clr); - PixelSetAA(x+dx,y-dy,clr); - PixelSetAA(x-dx,y-dy,clr); - } -//+------------------------------------------------------------------+ -//| Draw solid segment for vertical thick line | -//+------------------------------------------------------------------+ -void CCanvas::SegmentVertical(const int x,const int y1,const int y2,const int ysign,const double r,const uint clr,ENUM_LINE_END end_style) - { -//--- compute the constol points of the solid segment - int ye1,ye2; - int ys1,ys2; - switch(end_style) - { - case LINE_END_ROUND: - { - ye1=y1; - ye2=y2; - ys1=y1-(int)(ysign*r); - ys2=y2+(int)(ysign*r); - break; - } - case LINE_END_BUTT: - { - ye1=y1; - ye2=y2; - ys1=y1; - ys2=y2; - break; - } - case LINE_END_SQUARE: - { - ye1=y1-(int)(ysign*r); - ye2=y2+(int)(ysign*r); - ys1=ye1; - ys2=ye2; - break; - } - default: - return; - }; -//--- darw solid segment - for(int i=0; i<=MathAbs(ys2-ys1); i++) - { - double yi=ys1+(ysign*i); - for(int j=0; j<2*r; j++) - { - double xi=x-r+j; - double dist=DistancePointSegment(xi,yi,x,ye1,x,ye2); - double val=MathAbs(dist/r); - PixelTransform((int)xi,(int)yi,clr,FilterFunction(val)); - } - } - } -//+------------------------------------------------------------------+ -//| Draw solid segment for horizontal thick line | -//+------------------------------------------------------------------+ -void CCanvas::SegmentHorizontal(const int x1,const int x2,const int y,const int xsign,const double r,const uint clr,ENUM_LINE_END end_style) - { -//--- compute the constol points of the solid segment - int xe1,xe2; - int xs1,xs2; - switch(end_style) - { - case LINE_END_ROUND: - { - xe1=x1; - xe2=x2; - xs1=x1-(int)(xsign*r); - xs2=x2+(int)(xsign*r); - break; - } - case LINE_END_BUTT: - { - xe1=x1; - xe2=x2; - xs1=x1; - xs2=x2; - break; - } - case LINE_END_SQUARE: - { - xe1=x1-(int)(xsign*r); - xe2=x2+(int)(xsign*r); - xs1=xe1; - xs2=xe2; - break; - } - default: - return; - }; -//--- draw solid segment - for(int i=0; i<=MathAbs(xs2-xs1); i++) - { - double xi=xs1+(xsign*i); - for(int j=0; j<2*r; j++) - { - double yi=y-r+j; - double dist=DistancePointSegment(xi,yi,xe1,y,xe2,y); - double val=MathAbs(dist/r); - PixelTransform((int)xi,(int)yi,clr,FilterFunction(val)); - } - } - } -//+------------------------------------------------------------------+ -//| Draw solid segment for thick line | -//+------------------------------------------------------------------+ -void CCanvas::Segment(const int x1,const int y1,const int x2,const int y2,const double kp0,const double kp1,const int xsign,const int ysign, - const double rcos_k,const double rsin_k,const double r,const uint clr,ENUM_LINE_END end_style) - { - if(x1==x2 && y1==y2) - return; - if(x1==x2) - { - SegmentVertical(x1,y1,y2,ysign,r,clr,end_style); - return; - } - if(y1==y2) - { - SegmentHorizontal(x1,x2,y1,xsign,r,clr,end_style); - return; - } -//--- compute the constol points of the solid segment - int xe1,ye1,xe2,ye2; - int xs1,ys1,xs2,ys2; - switch(end_style) - { - case LINE_END_ROUND: - { - xe1=x1; - ye1=y1; - xe2=x2; - ye2=y2; - xs1=x1-(xsign)*(int)(rsin_k); - ys1=y1-(ysign)*(int)(rcos_k); - xs2=x2+(xsign)*(int)(rsin_k); - ys2=y2+(ysign)*(int)(rcos_k); - break; - } - case LINE_END_BUTT: - { - xe1=x1; - ye1=y1; - xe2=x2; - ye2=y2; - xs1=x1; - ys1=y1; - xs2=x2; - ys2=y2; - break; - } - case LINE_END_SQUARE: - { - xe1=x1-(xsign)*(int)(rsin_k); - ye1=y1-(ysign)*(int)(rcos_k); - xe2=x2+(xsign)*(int)(rsin_k); - ye2=y2+(ysign)*(int)(rcos_k); - xs1=xe1; - ys1=ye1; - xs2=xe2; - ys2=ye2; - break; - } - default: - return; - }; -//--- compute the four corners of the wide line - double p0x=xs1+(xsign)*(rcos_k); - double p0y=ys1-(ysign)*(rsin_k); - double p1x=xs1-(xsign)*(rcos_k); - double p1y=ys1+(ysign)*(rsin_k); - double p2x=xs2+(xsign)*(rcos_k); - double p2y=ys2-(ysign)*(rsin_k); - double p3x=xs2-(xsign)*(rcos_k); - double p3y=ys2+(ysign)*(rsin_k); -//--- draw solid segment - if(MathAbs(kp0)>=1) - { - double xi0,xi1; - double height=MathAbs(p3y-p0y); - for(int i=0; i<=height; i++) - { - double y=p0y+(ysign*i); - double xi00 = MathRound(p0x + (y-p0y)/kp0); - double xi01 = MathRound(p1x + (y-p1y)/kp1); - double xi02 = MathRound(p2x + (y-p2y)/kp1); - double xi03 = MathRound(p3x + (y-p3y)/kp0); - if(xsign==1) - { - xi0 = MathMax(xi00,xi01); - xi1 = MathMin(xi02,xi03); - } - else - { - xi0 = MathMin(xi00,xi01); - xi1 = MathMax(xi02,xi03); - } - double width=MathAbs(MathRound(xi1-xi0)); - for(int j=0; j<=width; j++) - { - double xi=xi0+(xsign*j); - double dist=DistancePointSegment(xi,y,xe1,ye1,xe2,ye2); - double val = MathAbs(dist/r); - PixelTransform((int)xi,(int)y,clr,FilterFunction(val)); - } - } - } - else - { - double yi0,yi1; - double width=MathAbs(p2x-p1x); - for(int i=0; i<=width; i++) - { - double x=p1x+(xsign*i); - double yi00 = MathRound(p0y + (x-p0x)*kp0); - double yi01 = MathRound(p1y + (x-p1x)*kp1); - double yi02 = MathRound(p2y + (x-p2x)*kp1); - double yi03 = MathRound(p3y + (x-p3x)*kp0); - if(ysign==1) - { - yi0 = MathMax(yi00,yi02); - yi1 = MathMin(yi01,yi03); - } - else - { - yi0 = MathMin(yi00,yi02); - yi1 = MathMax(yi01,yi03); - } - double height=MathAbs(yi1-yi0); - for(int j=0; j<=height; j++) - { - double yi=yi0+(ysign*j); - double dist=DistancePointSegment(x,yi,xe1,ye1,xe2,ye2); - double val=MathAbs(dist/r); - PixelTransform((int)x,(int)yi,clr,FilterFunction(val)); - } - } - } - } -//+------------------------------------------------------------------+ -//| Filter function for calculating alpha channel | -//+------------------------------------------------------------------+ -double CCanvas::FilterFunction(const double x) - { - if(x<=0.8) - return(1.0); - else - return MathExp(-(x-0.8)*(x-0.8)*50); - } -//+------------------------------------------------------------------+ -//| Calculate distance between point and segment | -//+------------------------------------------------------------------+ -double CCanvas::DistancePointSegment(const double px,const double py,const double x1,const double y1,const double x2,const double y2) - { -//--- primary calculate - double a=(px-x1)*(px-x1)+(py-y1)*(py-y1); - double b=(px-x2)*(px-x2)+(py-y2)*(py-y2); - double c=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1); -//--- check - if(a>=b+c) - return (MathSqrt(b)); - if(b>=a+c) - return (MathSqrt(a)); -//--- calculate distance - a=MathSqrt(a); - b=MathSqrt(b); - c=MathSqrt(c); - double p=(a+b+c)/2; - double s=MathSqrt((p-a)*(p-b)*(p-c)*p); -//--- check distance - if(MathIsValidNumber(s)) - return(s*2.0/c); - else - return(0); - } -//+------------------------------------------------------------------+ -//| Draw smothing polyline | -//+------------------------------------------------------------------+ -void CCanvas::PolylineSmooth(const int &x[],const int &y[],const uint clr,const int size,ENUM_LINE_STYLE style=STYLE_SOLID, - ENUM_LINE_END end_style=LINE_END_ROUND,double tension=0.5,double step=10) - { -//--- - int arr_size= ArraySize(x); - if(arr_size!=ArraySize(y)) - return; -//--- - double x1,x2,y1,y2; - tension*=0.3; -//--- coordinates of Bezier curve - int xc[]; - int yc[]; -//--- initialize control points - double ptX[]; - double ptY[]; - int size_pt=arr_size*3-2; - - ArrayResize(ptX,size_pt); - ArrayResize(ptY,size_pt); -//--- calculation of control points - CalcCurveBezierEndp(x[0],y[0],x[1],y[1],tension,x1,y1); - - ptX[0] = x[0]; - ptY[0] = y[0]; - ptX[1] = x1; - ptY[1] = y1; - - for(int i=0; i0.0) ?(int)(distance/step) : 1; - if(size_i<1) - size_i=2; - ArrayResize(xc,ArraySize(xc)+size_i,1024); - ArrayResize(yc,ArraySize(yc)+size_i,1024); - for(int t=0; t0.0) ?(int)(distance/step) : 1; - if(size_i<1) - size_i=2; - ArrayResize(xc,ArraySize(xc)+size_i,1024); - ArrayResize(yc,ArraySize(yc)+size_i,1024); - for(int t=0; t0.0) ?(int)(distance/step) : 1; - if(size_i<1) - size_i=2; - ArrayResize(xc,ArraySize(xc)+size_i,1024); - ArrayResize(yc,ArraySize(yc)+size_i,1024); - for(int t=0; t -#include -#include -//--- enumerations -enum ENUM_SHOW_FLAGS - { - FLAG_SHOW_NONE =0, - FLAG_SHOW_LEGEND =1, - FLAG_SHOW_SCALE_LEFT =2, - FLAG_SHOW_SCALE_RIGHT =4, - FLAG_SHOW_SCALE_TOP =8, - FLAG_SHOW_SCALE_BOTTOM=16, - FLAG_SHOW_GRID =32, - FLAG_SHOW_DESCRIPTORS =64, - FLAG_SHOW_VALUE =128, - FLAG_SHOW_PERCENT =256, - FLAGS_SHOW_SCALES =(FLAG_SHOW_SCALE_LEFT+FLAG_SHOW_SCALE_RIGHT+ - FLAG_SHOW_SCALE_TOP+FLAG_SHOW_SCALE_BOTTOM), - FLAGS_SHOW_ALL =(FLAG_SHOW_LEGEND+FLAGS_SHOW_SCALES+FLAG_SHOW_GRID+ - FLAG_SHOW_DESCRIPTORS+FLAG_SHOW_VALUE+FLAG_SHOW_PERCENT) - }; -enum ENUM_ALIGNMENT - { - ALIGNMENT_LEFT = 1, // align by left border - ALIGNMENT_TOP = 2, // align by top border - ALIGNMENT_RIGHT = 4, // align by right border - ALIGNMENT_BOTTOM = 8 // align by bottom border - }; -//--- macro -#define IS_SHOW_LEGEND ((m_show_flags&FLAG_SHOW_LEGEND) !=0) -#define IS_SHOW_SCALES ((m_show_flags&FLAGS_SHOW_SCALES) !=0) -#define IS_SHOW_SCALE_LEFT ((m_show_flags&FLAG_SHOW_SCALE_LEFT) !=0) -#define IS_SHOW_SCALE_RIGHT ((m_show_flags&FLAG_SHOW_SCALE_RIGHT) !=0) -#define IS_SHOW_SCALE_TOP ((m_show_flags&FLAG_SHOW_SCALE_TOP) !=0) -#define IS_SHOW_SCALE_BOTTOM ((m_show_flags&FLAG_SHOW_SCALE_BOTTOM)!=0) -#define IS_SHOW_GRID ((m_show_flags&FLAG_SHOW_GRID) !=0) -#define IS_SHOW_DESCRIPTORS ((m_show_flags&FLAG_SHOW_DESCRIPTORS) !=0) -#define IS_SHOW_VALUE ((m_show_flags&FLAG_SHOW_VALUE) !=0) -#define IS_SHOW_PERCENT ((m_show_flags&FLAG_SHOW_PERCENT) !=0) -//+------------------------------------------------------------------+ -//| Class CChartCanvas | -//| Usage: base class for graphical charts | -//+------------------------------------------------------------------+ -class CChartCanvas : public CCanvas - { -protected: - //--- colors - uint m_color_background; - uint m_color_border; - uint m_color_text; - uint m_color_grid; - //--- adjusted parameters - uint m_max_data; - uint m_max_descr_len; - uint m_allowed_show_flags; - uint m_show_flags; - ENUM_ALIGNMENT m_legend_alignment; - uint m_threshold_drawing; - bool m_accumulative; - //--- parameters for scales and grid - double m_v_scale_min; - double m_v_scale_max; - uint m_num_grid; - int m_scale_digits; - //--- data - int m_data_offset; - uint m_data_total; - CArray *m_data; - CArrayInt m_colors; - CArrayString m_descriptors; - //--- - CArrayInt m_index; - uint m_index_size; - double m_sum; - double m_others; - uint m_max_descr_width; - uint m_max_value_width; - //--- variables - CRect m_data_area; - //--- variables for scaling and scales - double m_scale_x; - int m_x_min; - int m_x_0; - int m_x_max; - int m_dx_grid; - double m_scale_y; - int m_y_min; - int m_y_0; - int m_y_max; - int m_dy_grid; - string m_scale_text[]; - -public: - CChartCanvas(void); - ~CChartCanvas(void); - //--- create - virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - //--- colors - uint ColorBackground(void) const { return(m_color_background); } - void ColorBackground(const uint value); - uint ColorBorder(void) const { return(m_color_border); } - void ColorBorder(const uint value); - uint ColorText(void) const { return(m_color_text); } - void ColorText(const uint value); - uint ColorGrid(void) const { return(m_color_grid); } - void ColorGrid(const uint value) { m_color_grid=value; } - //--- adjusted parameters - uint MaxData(void) const { return(m_max_data); } - void MaxData(const uint value); - uint MaxDescrLen(void) const { return(m_max_descr_len); } - void MaxDescrLen(const uint value); - //--- show flags - void AllowedShowFlags(const uint flags); - uint ShowFlags(void) const { return(m_show_flags); } - void ShowFlags(const uint flags); - bool IsShowLegend(void) const { return(IS_SHOW_LEGEND); } - bool IsShowScaleLeft(void) const { return(IS_SHOW_SCALE_LEFT); } - bool IsShowScaleRight(void) const { return(IS_SHOW_SCALE_RIGHT); } - bool IsShowScaleTop(void) const { return(IS_SHOW_SCALE_TOP); } - bool IsShowScaleBottom(void) const { return(IS_SHOW_SCALE_BOTTOM); } - bool IsShowGrid(void) const { return(IS_SHOW_GRID); } - bool IsShowDescriptors(void) const { return(IS_SHOW_DESCRIPTORS); } - bool IsShowPercent(void) const { return(IS_SHOW_PERCENT); } - void ShowLegend(const bool flag=true); - void ShowScaleLeft(const bool flag=true); - void ShowScaleRight(const bool flag=true); - void ShowScaleTop(const bool flag=true); - void ShowScaleBottom(const bool flag=true); - void ShowGrid(const bool flag=true); - void ShowDescriptors(const bool flag=true); - void ShowValue(const bool flag=true); - void ShowPercent(const bool flag=true); - void LegendAlignment(const ENUM_ALIGNMENT value); - void Accumulative(const bool flag=true); - //--- for scales and grid - double VScaleMin(void) const { return(m_v_scale_min); } - void VScaleMin(const double value); - double VScaleMax(void) const { return(m_v_scale_max); } - void VScaleMax(const double value); - uint NumGrid(void) const { return(m_num_grid); } - void NumGrid(const uint value); - void VScaleParams(const double max,const double min,const uint grid); - //--- state - int DataOffset(void) const { return(m_data_offset); } - void DataOffset(const int value); - //--- data - uint DataTotal(void) const { return(m_data_total); } - bool DescriptorUpdate(const uint pos,const string descr); - bool ColorUpdate(const uint pos,const uint clr); - -protected: - virtual void ValuesCheck(void); - virtual void Redraw(void); - virtual void DrawBackground(void); - virtual void DrawLegend(void); - int DrawLegendVertical(const int w,const int h); - int DrawLegendHorizontal(const int w,const int h); - virtual void CalcScales(void); - virtual void DrawScales(void); - virtual int DrawScaleLeft(const bool draw=true); - virtual int DrawScaleRight(const bool draw=true); - virtual int DrawScaleTop(const bool draw=true); - virtual int DrawScaleBottom(const bool draw=true); - virtual void DrawGrid(void); - virtual void DrawDescriptors(void) {} - virtual void DrawChart(void); - virtual void DrawData(const uint idx=0) {} - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CChartCanvas::CChartCanvas(void) : m_color_background(XRGB(0xFF,0xFF,0xFF)), - m_color_border(XRGB(0x9F,0x9F,0x9F)), - m_color_text(XRGB(0x3F,0x3F,0x3F)), - m_color_grid(XRGB(0xCF,0xCF,0xCF)), - m_max_data(10), - m_max_descr_len(10), - m_allowed_show_flags(FLAGS_SHOW_ALL), - m_show_flags(FLAG_SHOW_NONE), - m_legend_alignment(ALIGNMENT_BOTTOM), - m_threshold_drawing(2), - m_accumulative(false), - m_data_offset(0), - m_data_total(0), - m_data(NULL), - m_v_scale_min(0.0), - m_v_scale_max(10.0), - m_num_grid(5), - m_scale_digits(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CChartCanvas::~CChartCanvas(void) - { - if(m_data!=NULL) - delete m_data; - } -//+------------------------------------------------------------------+ -//| Create dynamic resource | -//+------------------------------------------------------------------+ -bool CChartCanvas::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { -//--- call method of parent class - if(!CCanvas::Create(name,width,height,clrfmt)) - return(false); -//--- set font - FontSet("Tahoma",-100); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Sets background color | -//+------------------------------------------------------------------+ -void CChartCanvas::ColorBackground(const uint value) - { - m_color_background=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets border color | -//+------------------------------------------------------------------+ -void CChartCanvas::ColorBorder(const uint value) - { - m_color_border=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets text color | -//+------------------------------------------------------------------+ -void CChartCanvas::ColorText(const uint value) - { - m_color_text=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets maximum amount of data | -//+------------------------------------------------------------------+ -void CChartCanvas::MaxData(const uint value) - { -//--- check - if((value==0) || (m_data_total==value)) - return; -//--- save - m_max_data=value; - if(m_data_total>m_max_data) - { - m_data_total=value; - m_colors.Resize(value); - m_descriptors.Resize(value); - } - } -//+------------------------------------------------------------------+ -//| Sets maximum length of descriptor | -//+------------------------------------------------------------------+ -void CChartCanvas::MaxDescrLen(const uint value) - { - m_max_descr_len=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets allowed visibility flags | -//+------------------------------------------------------------------+ -void CChartCanvas::AllowedShowFlags(const uint flags) - { - m_allowed_show_flags=flags; - m_show_flags&=m_allowed_show_flags; - } -//+------------------------------------------------------------------+ -//| Sets visibility flags | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowFlags(const uint flags) - { - m_show_flags=flags&m_allowed_show_flags; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for "legend" | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowLegend(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_LEGEND)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_LEGEND; - else - m_show_flags&=~FLAG_SHOW_LEGEND; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for left scale | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowScaleLeft(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_SCALE_LEFT)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_SCALE_LEFT; - else - m_show_flags&=~FLAG_SHOW_SCALE_LEFT; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for right scale | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowScaleRight(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_SCALE_RIGHT)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_SCALE_RIGHT; - else - m_show_flags&=~FLAG_SHOW_SCALE_RIGHT; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for top scale | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowScaleTop(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_SCALE_TOP)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_SCALE_TOP; - else - m_show_flags&=~FLAG_SHOW_SCALE_TOP; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for bottom scale | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowScaleBottom(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_SCALE_BOTTOM)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_SCALE_BOTTOM; - else - m_show_flags&=~FLAG_SHOW_SCALE_BOTTOM; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for grid | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowGrid(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_GRID)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_GRID; - else - m_show_flags&=~FLAG_SHOW_GRID; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for descriptors | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowDescriptors(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_DESCRIPTORS)!=0) - { - if(flag) - m_show_flags|=FLAG_SHOW_DESCRIPTORS; - else - m_show_flags&=~FLAG_SHOW_DESCRIPTORS; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for value | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowValue(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_VALUE)!=0) - { - if(flag) - { - m_show_flags|=FLAG_SHOW_VALUE; - m_show_flags&=~FLAG_SHOW_PERCENT; - } - else - m_show_flags&=~FLAG_SHOW_VALUE; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets visibility flag for percentage | -//+------------------------------------------------------------------+ -void CChartCanvas::ShowPercent(const bool flag) - { - if((m_allowed_show_flags&FLAG_SHOW_PERCENT)!=0) - { - if(flag) - { - m_show_flags|=FLAG_SHOW_PERCENT; - m_show_flags&=~FLAG_SHOW_VALUE; - } - else - m_show_flags&=~FLAG_SHOW_PERCENT; - //--- redraw - if(m_data_total>0) - Redraw(); - } - } -//+------------------------------------------------------------------+ -//| Sets legend alignment | -//+------------------------------------------------------------------+ -void CChartCanvas::LegendAlignment(const ENUM_ALIGNMENT value) - { - m_legend_alignment=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets accumulative flag | -//+------------------------------------------------------------------+ -void CChartCanvas::Accumulative(const bool flag=true) - { - m_accumulative=flag; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets lower limit for vertical scale | -//+------------------------------------------------------------------+ -void CChartCanvas::VScaleMin(const double value) - { -//--- check - if(value==m_v_scale_max) - return; -//--- save - m_v_scale_min=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets upper limit for vertical scale | -//+------------------------------------------------------------------+ -void CChartCanvas::VScaleMax(const double value) - { - if(value==m_v_scale_min) - return; -//--- save - m_v_scale_max=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets number of vertical scale divisions | -//+------------------------------------------------------------------+ -void CChartCanvas::NumGrid(const uint value) - { -//--- check - if(value==0) - return; -//--- save - m_num_grid=value; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets parameters for vertical scale | -//+------------------------------------------------------------------+ -void CChartCanvas::VScaleParams(const double max,const double min,const uint grid) - { -//--- check - if(grid==0) - return; - if(max<=min) - return; -//--- save - m_v_scale_max=max; - m_v_scale_min=min; - m_num_grid =grid; -//--- redraw - if(m_data_total>0) - Redraw(); - } -//+------------------------------------------------------------------+ -//| Sets data offset | -//+------------------------------------------------------------------+ -void CChartCanvas::DataOffset(const int value) - { - m_data_offset=value; -//--- redraw - Redraw(); - } -//+------------------------------------------------------------------+ -//| Updates parameter descriptor only (in specified position) | -//+------------------------------------------------------------------+ -bool CChartCanvas::DescriptorUpdate(const uint pos,const string descr) - { -//--- update - if(descr!=NULL && !m_descriptors.Update(pos,descr)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates parameter color only (in specified position) | -//+------------------------------------------------------------------+ -bool CChartCanvas::ColorUpdate(const uint pos,const uint clr) - { -//--- update - if(clr!=0 && !m_colors.Update(pos,clr)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Checks values for insignificance | -//+------------------------------------------------------------------+ -void CChartCanvas::ValuesCheck(void) - { - string text; - uint w,h; -//--- clear - m_max_value_width=0; - m_sum =0; - m_others =0; - m_index_size =0; - m_index.Clear(); -//--- check - if(m_data==NULL) - return; - if(m_data.Type()==TYPE_DOUBLE) - { - //--- single-series chart - //--- calculate sum of all values - for(uint i=0;im_height) - { - cols++; - rows=(int)m_index_size/cols; - if((int)m_index_size%cols!=0) - rows++; - } -//--- draw - int x0=(m_legend_alignment==ALIGNMENT_RIGHT) ? width-w*cols+h : h; - int x=0; - int y =-h/2; - int i; - if(m_data_total==m_index_size) - { - for(i=0;i<(int)m_data_total;i++,x+=w) - { - if(i%cols==0) - { - x=x0; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,(uint)m_colors[i]); - TextOut(x+h,y," - "+m_descriptors[i],m_color_text); - } - } - else - { - for(i=0;i<(int)m_index_size;i++,x+=w) - { - int index=m_index[i]; - if(i%cols==0) - { - x=x0; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,(uint)m_colors[index]); - TextOut(x+h,y," - "+m_descriptors[index],m_color_text); - } - if(i%cols==0) - { - x=x0; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,COLOR2RGB(clrBlack)); - TextOut(x+h,y," - Others",m_color_text); - } -//--- width - return(w*cols); - } -//+------------------------------------------------------------------+ -//| Draw horizontal "legend" | -//+------------------------------------------------------------------+ -int CChartCanvas::DrawLegendHorizontal(const int w,const int h) - { - int width =m_data_area.Width(); - int height=m_data_area.Height(); - int rows =1; - int cols =(int)m_index_size; -//--- calculate - while(w*cols>m_width) - { - rows++; - cols=(int)m_index_size/rows; - if((int)m_index_size%rows!=0) - cols++; - } -//--- draw - int dx=width/(cols+1); - int x =dx-w/2+h; - int dy=(int)(1.5*h); - int y =(m_legend_alignment==ALIGNMENT_BOTTOM) ? height-dy*(rows+1) : -h/2; - int i; - if(m_data_total==m_index_size) - { - for(i=0;i<(int)m_data_total;i++,x+=dx) - { - if(i%cols==0) - { - x=dx-w/2+h; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,(uint)m_colors[i]); - TextOut(x+h,y," - "+m_descriptors[i],m_color_text); - } - } - else - { - for(i=0;i<(int)m_index_size;i++,x+=dx) - { - int index=m_index[i]; - if(i%cols==0) - { - x=dx-w/2+h; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,(uint)m_colors[index]); - TextOut(x+h,y," - "+m_descriptors[index],m_color_text); - } - if(i%cols==0) - { - x=dx-w/2+h; - y+=dy; - } - FillRectangle(x,y,x+h,y+h,COLOR2RGB(clrBlack)); - TextOut(x+h,y," - Others",m_color_text); - } -//--- height - return(dy*(rows+1)); - } -//+------------------------------------------------------------------+ -//| Calculates coordinates of scales | -//+------------------------------------------------------------------+ -void CChartCanvas::CalcScales(void) - { - int width =m_data_area.Width(); - int height=m_data_area.Height(); -//--- limits - m_y_max=m_data_area.top+DrawScaleTop(false); - m_y_min=m_data_area.bottom-DrawScaleBottom(false); -//--- additional - m_dy_grid=(int)((m_y_min-m_y_max)/m_num_grid); - m_y_max+=(int)(((m_y_min-m_y_max)-m_dy_grid*m_num_grid)/2); - m_y_min=(int)(m_y_max+m_dy_grid*m_num_grid); -//--- normalize - if(m_v_scale_min>=0.0) - m_y_0=m_y_min; - else - { - if(m_v_scale_max<=0.0) - m_y_0=m_y_max; - else - m_y_0=(int)(m_y_max+(m_y_min-m_y_max)*m_v_scale_max/(m_v_scale_max-m_v_scale_min)); - } -//--- scale - m_scale_y=(m_v_scale_max!=m_v_scale_min) ? (m_y_min-m_y_max)/(m_v_scale_max-m_v_scale_min) : 1; -//--- labels on scale - if(ArraySize(m_scale_text)!=m_num_grid+1 && ArrayResize(m_scale_text,m_num_grid+1)==-1) - return; - double val=m_v_scale_min; - double dval=(m_v_scale_max-m_v_scale_min)/m_num_grid; - for(uint i=0;i<=m_num_grid;i++,val+=dval) - m_scale_text[i]=DoubleToString(val,m_scale_digits); - } -//+------------------------------------------------------------------+ -//| Redraws scales | -//+------------------------------------------------------------------+ -void CChartCanvas::DrawScales(void) - { -//--- recalculate - CalcScales(); -//--- redraw scales - if(IS_SHOW_SCALE_LEFT) - DrawScaleLeft(); - if(IS_SHOW_SCALE_RIGHT) - DrawScaleRight(); - if(IS_SHOW_SCALE_TOP) - DrawScaleTop(); - if(IS_SHOW_SCALE_BOTTOM) - DrawScaleBottom(); - } -//+------------------------------------------------------------------+ -//| Redraws left scale | -//+------------------------------------------------------------------+ -int CChartCanvas::DrawScaleLeft(const bool draw) - { -//--- check flag - if(!IS_SHOW_SCALE_LEFT) - return(0); -//--- variables - int x1=m_data_area.left; - int x2; - int y=m_y_min; -//--- calculate scale width - int size=0; - for(uint i=0;i<=m_num_grid;i++) - { - if(size -//+------------------------------------------------------------------+ -//| Class CHistogramChart | -//| Usage: generates histogram chart | -//+------------------------------------------------------------------+ -class CHistogramChart : public CChartCanvas - { -private: - //--- colors - uint m_fill_brush[]; - //--- adjusted parameters - bool m_gradient; - uint m_bar_gap; - uint m_bar_min_size; - uint m_bar_border; - //--- data - CArrayObj *m_values; - -public: - CHistogramChart(void); - ~CHistogramChart(void); - //--- create - virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_ARGB_NORMALIZE); - //--- adjusted parameters - void Gradient(const bool flag=true) { m_gradient=flag; } - void BarGap(const uint value) { m_bar_gap=value; } - void BarMinSize(const uint value) { m_bar_min_size=value; } - void BarBorder(const uint value) { m_bar_border=value; } - //--- data - bool SeriesAdd(const double &value[],const string descr="",const uint clr=0); - bool SeriesInsert(const uint pos,const double &value[],const string descr="",const uint clr=0); - bool SeriesUpdate(const uint pos,const double &value[],const string descr=NULL,const uint clr=0); - bool SeriesDelete(const uint pos); - bool ValueUpdate(const uint series,const uint pos,double value); - -protected: - virtual void DrawData(const uint idx); - void DrawBar(const int x,const int y,const int w,const int h,const uint clr); - void GradientBrush(const int size,const uint fill_clr); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CHistogramChart::CHistogramChart(void) : m_gradient(true), - m_bar_gap(3), - m_bar_min_size(5), - m_bar_border(0) - { - ShowFlags(FLAG_SHOW_LEGEND|FLAGS_SHOW_SCALES|FLAG_SHOW_GRID); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CHistogramChart::~CHistogramChart(void) - { - if(ArraySize(m_fill_brush)!=0) - ArrayFree(m_fill_brush); - } -//+------------------------------------------------------------------+ -//| Create dynamic resource | -//+------------------------------------------------------------------+ -bool CHistogramChart::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { -//--- create object to store data - if((m_values=new CArrayObj)==NULL) - return(false); -//--- pass responsibility for its destruction to the parent class - m_data=m_values; -//--- call method of parent class - if(!CChartCanvas::Create(name,width,height,clrfmt)) - return(false); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Adds data series | -//+------------------------------------------------------------------+ -bool CHistogramChart::SeriesAdd(const double &value[],const string descr,const uint clr) - { -//--- check - if(m_data_total==m_max_data) - return(false); -//--- add - CArrayDouble *arr=new CArrayDouble; - if(!m_values.Add(arr)) - return(false); - if(!arr.AssignArray(value)) - return(false); - if(!m_colors.Add((clr==0) ? GetDefaultColor(m_data_total) : clr)) - return(false); - if(!m_descriptors.Add(descr)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Inserts data series | -//+------------------------------------------------------------------+ -bool CHistogramChart::SeriesInsert(const uint pos,const double &value[],const string descr,const uint clr) - { -//--- check - if(m_data_total==m_max_data) - return(false); - if(pos>=m_data_total) - return(false); -//--- insert - CArrayDouble *arr=new CArrayDouble; - if(!m_values.Insert(arr,pos)) - return(false); - if(!arr.AssignArray(value)) - return(false); - if(!m_colors.Insert((clr==0) ? GetDefaultColor(m_data_total) : clr,pos)) - return(false); - if(!m_descriptors.Insert(descr,pos)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates data series | -//+------------------------------------------------------------------+ -bool CHistogramChart::SeriesUpdate(const uint pos,const double &value[],const string descr,const uint clr) - { -//--- check - if(pos>=m_data_total) - return(false); - CArrayDouble *data=m_values.At(pos); - if(data==NULL) - return(false); -//--- update - if(!data.AssignArray(value)) - return(false); - if(clr!=0 && !m_colors.Update(pos,clr)) - return(false); - if(descr!=NULL && !m_descriptors.Update(pos,descr)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Deletes data series | -//+------------------------------------------------------------------+ -bool CHistogramChart::SeriesDelete(const uint pos) - { -//--- check - if(pos>=m_data_total && m_data_total!=0) - return(false); -//--- delete - if(!m_values.Delete(pos)) - return(false); - m_data_total--; - if(!m_colors.Delete(pos)) - return(false); - if(!m_descriptors.Delete(pos)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates element in data series | -//+------------------------------------------------------------------+ -bool CHistogramChart::ValueUpdate(const uint series,const uint pos,double value) - { - CArrayDouble *data=m_values.At(series); -//--- check - if(data==NULL) - return(false); -//--- update - if(!data.Update(pos,value)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Draws histogram | -//+------------------------------------------------------------------+ -void CHistogramChart::DrawData(const uint idx) - { - double value=0.0; -//--- check - CArrayDouble *data=m_values.At(idx); - if(data==NULL) - return; - int total=data.Total(); - if(total==0 || (int)idx>=total) - return; -//--- calculate - int x1=m_data_area.left; - int x2=m_data_area.right; - int dx=(x2-x1)/total; - uint clr=m_colors[idx]; - uint w=dx/m_data_total; - if(w0) - { - y=(m_y_0-(int)(value*m_scale_y)); - h=m_y_0-y; - } - else - { - y=m_y_0; - h=-(int)(value*m_scale_y); - } - DrawBar(x,y,w,h,clr); - //--- draw text of value - if(IS_SHOW_VALUE) - { - string text =DoubleToString(value,2); - int width=(int)(TextWidth(text)+w); - if(value>0) - { - if(width>y-m_y_max) - TextOut(x+w/2,y+w,text,m_color_text,TA_RIGHT|TA_VCENTER); - else - TextOut(x+w/2,y-w,text,m_color_text,TA_LEFT|TA_VCENTER); - } - else - { - if(width>m_y_min-y-h) - TextOut(x+w/2,y+h-w,text,m_color_text,TA_LEFT|TA_VCENTER); - else - TextOut(x+w/2,y+h+w,text,m_color_text,TA_RIGHT|TA_VCENTER); - } - } - } - if(IS_SHOW_VALUE) - FontSet(fontname,fontsize,fontflags,fontangle); - } -//+------------------------------------------------------------------+ -//| Draws bar | -//+------------------------------------------------------------------+ -void CHistogramChart::DrawBar(const int x,const int y,const int w,const int h,const uint clr) - { -//--- draw bar - if(!m_gradient || ArraySize(m_fill_brush)>1; - if((r&1)==0) - i1--; - //--- calculate - while(dy>=dx) - { - clr=fill_clr; - dclr=GETRGB(XRGB((r-dy)*GETRGBR(clr)/r,(r-dy)*GETRGBG(clr)/r,(r-dy)*GETRGBB(clr)/r)); - clr-=dclr; - m_fill_brush[i1]=clr; - m_fill_brush[i2]=clr; - //--- - if(f>=0) - { - dy--; - dd_y+=2; - f+=dd_y; - } - dx++; - if(--i1<0) - break; - i2++; - dd_x+=2; - f+=dd_x; - } - } - else - ArrayFree(m_fill_brush); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/Charts/LineChart.mqh b/Include/Canvas/Charts/LineChart.mqh deleted file mode 100644 index c81e9e3..0000000 --- a/Include/Canvas/Charts/LineChart.mqh +++ /dev/null @@ -1,383 +0,0 @@ -//+------------------------------------------------------------------+ -//| LineChart.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "ChartCanvas.mqh" -#include -//+------------------------------------------------------------------+ -//| Class CLineChart | -//| Usage: generates line chart | -//+------------------------------------------------------------------+ -class CLineChart : public CChartCanvas - { -private: - //--- data - CArrayObj *m_values; - //--- adjusted parameters - bool m_filled; - -public: - CLineChart(void); - ~CLineChart(void); - //--- create - virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_ARGB_NORMALIZE); - //--- adjusted parameters - void Filled(const bool flag=true) { m_filled=flag; } - //--- set up - bool SeriesAdd(const double &value[],const string descr="",const uint clr=0); - bool SeriesInsert(const uint pos,const double &value[],const string descr="",const uint clr=0); - bool SeriesUpdate(const uint pos,const double &value[],const string descr=NULL,const uint clr=0); - bool SeriesDelete(const uint pos); - bool ValueUpdate(const uint series,const uint pos,double value); - -protected: - virtual void DrawChart(void); - virtual void DrawData(const uint index=0); - -private: - double CalcArea(const uint index); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CLineChart::CLineChart(void) : m_filled(false) - { - ShowFlags(FLAG_SHOW_LEGEND|FLAGS_SHOW_SCALES|FLAG_SHOW_GRID); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CLineChart::~CLineChart(void) - { - } -//+------------------------------------------------------------------+ -//| Create dynamic resource | -//+------------------------------------------------------------------+ -bool CLineChart::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { -//--- create object to store data - if((m_values=new CArrayObj)==NULL) - return(false); -//--- pass responsibility for its destruction to the parent class - m_data=m_values; -//--- call method of parent class - if(!CChartCanvas::Create(name,width,height,clrfmt)) - return(false); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Adds data series | -//+------------------------------------------------------------------+ -bool CLineChart::SeriesAdd(const double &value[],const string descr,const uint clr) - { -//--- check - if(m_data_total==m_max_data) - return(false); -//--- add - CArrayDouble *arr=new CArrayDouble; - if(!m_values.Add(arr)) - return(false); - if(!arr.AssignArray(value)) - return(false); - if(!m_colors.Add((clr==0) ? GetDefaultColor(m_data_total) : clr)) - return(false); - if(!m_descriptors.Add(descr)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Inserts data series | -//+------------------------------------------------------------------+ -bool CLineChart::SeriesInsert(const uint pos,const double &value[],const string descr,const uint clr) - { -//--- check - if(m_data_total==m_max_data) - return(false); - if(pos>=m_data_total) - return(false); -//--- insert - CArrayDouble *arr=new CArrayDouble; - if(!m_values.Insert(arr,pos)) - return(false); - if(!arr.AssignArray(value)) - return(false); - if(!m_colors.Insert((clr==0) ? GetDefaultColor(m_data_total) : clr,pos)) - return(false); - if(!m_descriptors.Insert(descr,pos)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates data series | -//+------------------------------------------------------------------+ -bool CLineChart::SeriesUpdate(const uint pos,const double &value[],const string descr,const uint clr) - { -//--- check - if(pos>=m_data_total) - return(false); - CArrayDouble *data=m_values.At(pos); - if(data==NULL) - return(false); -//--- update - if(!data.AssignArray(value)) - return(false); - if(clr!=0 && !m_colors.Update(pos,clr)) - return(false); - if(descr!=NULL && !m_descriptors.Update(pos,descr)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Deletes data series | -//+------------------------------------------------------------------+ -bool CLineChart::SeriesDelete(const uint pos) - { -//--- check - if(pos>=m_data_total && m_data_total!=0) - return(false); -//--- delete - if(!m_values.Delete(pos)) - return(false); - m_data_total--; - if(!m_colors.Delete(pos)) - return(false); - if(!m_descriptors.Delete(pos)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates element in data series | -//+------------------------------------------------------------------+ -bool CLineChart::ValueUpdate(const uint series,const uint pos,double value) - { - CArrayDouble *data=m_values.At(series); -//--- check - if(data==NULL) - return(false); -//--- update - if(!data.Update(pos,value)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Redraws data | -//+------------------------------------------------------------------+ -void CLineChart::DrawChart(void) - { - if(m_filled) - { - //--- calculate areas of filling - double s[]; - ArrayResize(s,m_data_total); - ArrayInitialize(s,0); - for(uint i=0;im_y_0 && y2m_y_0)) - { - //--- draw two triangles - int x3; - if(y1>y2) - { - x3=x+dx*(y1-m_y_0)/(y1-y2); - FillTriangle(x,y1,x3,m_y_0,x,m_y_0,(uint)m_colors[index]); - FillTriangle(x+dx,y2,x3,m_y_0,x+dx,m_y_0,(uint)m_colors[index]); - } - else - { - x3=x+dx*(m_y_0-y1)/(y2-y1); - FillTriangle(x,y1,x3,m_y_0,x,m_y_0,(uint)m_colors[index]); - FillTriangle(x+dx,y2,x3,m_y_0,x+dx,m_y_0,(uint)m_colors[index]); - } - continue; - } - if(y1y2) - FillTriangle(x,y1,x+dx,y2,x+dx,y1,(uint)m_colors[index]); - if(y1m_y_0 || y2>m_y_0) - { - if(y1y2) - { - FillTriangle(x,y1,x+dx,y2,x,y2,(uint)m_colors[index]); - y1=y2; - } - } - FillRectangle(x,m_y_0,x+dx,y1,(uint)m_colors[index]); - } - else - LineAA(x,y1,x+dx,y2,(uint)m_colors[index],STYLE_SOLID); - } - } -//+------------------------------------------------------------------+ -//| Area of filling | -//+------------------------------------------------------------------+ -double CLineChart::CalcArea(const uint index) - { - double area =0; - double value=0; - int dx =100; -//--- - CArrayDouble *data=m_values.At(index); - if(data==NULL) - return(0); - int total=data.Total(); - if(total<=1) - return(0); - int y1=0; - int y2=(int)(m_y_0-data[0]*m_scale_y); - for(int i=0;im_y_0 && y2m_y_0)) - { - //--- line of values crosses the Y axis - int x; - if(y1>y2) - { - //--- from the bottom up - x=dx*(y1-m_y_0)/(y1-y2); - //--- add area of lower triangle - area+=x*(y1-m_y_0)/2; - //--- add area of upper triangle - area+=(dx-x)*(m_y_0-y2)/2; - } - else - { - //--- from top down - x=dx*(m_y_0-y1)/(y2-y1); - //--- add area of upper triangle - area+=x*(m_y_0-y1)/2; - //--- add area of lower triangle - area+=(dx-x)*(y2-m_y_0)/2; - } - continue; - } - if(y1y2) - { - //--- add area of triangle - area+=dx*(y1-y2)/2; - //--- add area of rectangle - area+=dx*(m_y_0-y2); - } - if(y1m_y_0 || y2>m_y_0) - { - //--- both values are less than zero - if(y1y2) - { - //--- add area of triangle - area+=dx*(y1-y2)/2; - //--- add area of rectangle - area+=dx*(y2-m_y_0); - } - } - } -//--- - return(area); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/Charts/PieChart.mqh b/Include/Canvas/Charts/PieChart.mqh deleted file mode 100644 index 79be4d1..0000000 --- a/Include/Canvas/Charts/PieChart.mqh +++ /dev/null @@ -1,414 +0,0 @@ -//+------------------------------------------------------------------+ -//| PieChart.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "ChartCanvas.mqh" -//+------------------------------------------------------------------+ -//| Class CPieChart | -//| Usage: generates pie chart | -//+------------------------------------------------------------------+ -class CPieChart : public CChartCanvas - { -private: - //--- data - CArrayDouble *m_values; - //--- for draw - int m_x0; - int m_y0; - int m_r; - -public: - CPieChart(void); - ~CPieChart(void); - //--- create - virtual bool Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt=COLOR_FORMAT_XRGB_NOALPHA); - //--- data - bool SeriesSet(const double &value[],const string &text[],const uint &clr[]); - bool ValueAdd(const double value,const string descr="",const uint clr=0); - bool ValueInsert(const uint pos,const double value,const string descr="",const uint clr=0); - bool ValueUpdate(const uint pos,const double value,const string descr=NULL,const uint clr=0); - bool ValueDelete(const uint pos); - -protected: - virtual void DrawChart(void); - void DrawPie(double fi3,double fi4,int idx,CPoint &p[],const uint clr); - string LabelMake(const string text,const double value,const bool to_left); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CPieChart::CPieChart(void) - { - uint flags=FLAG_SHOW_LEGEND|FLAG_SHOW_DESCRIPTORS|FLAG_SHOW_VALUE|FLAG_SHOW_PERCENT; - AllowedShowFlags(flags); - ShowFlags(flags); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CPieChart::~CPieChart(void) - { - } -//+------------------------------------------------------------------+ -//| Create dynamic resource | -//+------------------------------------------------------------------+ -bool CPieChart::Create(const string name,const int width,const int height,ENUM_COLOR_FORMAT clrfmt) - { -//--- create object to store data - if((m_values=new CArrayDouble)==NULL) - return(false); -//--- pass responsibility for its destruction to the parent class - m_data=m_values; -//--- call method of parent class - if(!CChartCanvas::Create(name,width,height,clrfmt)) - return(false); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Sets displayed parameters | -//+------------------------------------------------------------------+ -bool CPieChart::SeriesSet(const double &value[],const string &text[],const uint &clr[]) - { -//--- !!! user is responsible for correct filling of arrays !!! -//--- check - if(m_values==NULL) - return(false); -//--- set - if(!m_values.AssignArray(value)) - return(false); - if(!m_descriptors.AssignArray(text)) - return(false); - if(!m_colors.AssignArray(clr)) - return(false); - m_data_total=m_values.Total(); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Adds displayed parameter (to the end) | -//+------------------------------------------------------------------+ -bool CPieChart::ValueAdd(const double value,const string descr,const uint clr) - { -//--- check - if((value<=0)) - return(false); -//--- add - if(!m_values.Add(value)) - return(false); - if(!m_descriptors.Add(descr)) - return(false); - if(!m_colors.Add((clr==0) ? GetDefaultColor(m_data_total) : clr)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Inserts displayed parameter (to specified position) | -//+------------------------------------------------------------------+ -bool CPieChart::ValueInsert(const uint pos,const double value,const string descr,const uint clr) - { -//--- check - if((value<=0)) - return(false); -//--- insert - if(!m_values.Insert(value,pos)) - return(false); - if(!m_descriptors.Insert(descr,pos)) - return(false); - if(!m_colors.Insert((clr==0) ? GetDefaultColor(m_data_total) : clr,pos)) - return(false); - m_data_total++; -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Updates displayed parameter (in specified position) | -//+------------------------------------------------------------------+ -bool CPieChart::ValueUpdate(const uint pos,const double value,const string descr,const uint clr) - { -//--- check - if((value<=0)) - return(false); -//--- update - if(!m_values.Update(pos,value)) - return(false); - if(descr!=NULL && !m_descriptors.Update(pos,descr)) - return(false); - if(clr!=0 && !m_colors.Update(pos,clr)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Deletes displayed parameter (from specified position) | -//+------------------------------------------------------------------+ -bool CPieChart::ValueDelete(const uint pos) - { -//--- delete - if(!m_values.Delete(pos)) - return(false); - m_data_total--; - if(!m_descriptors.Delete(pos)) - return(false); - if(!m_colors.Delete(pos)) - return(false); -//--- redraw - Redraw(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Draws | -//+------------------------------------------------------------------+ -void CPieChart::DrawChart(void) - { -//--- check - if(m_data_total==0) - return; -//--- variables - string text=""; - double angle=M_PI*(m_data_offset%360)/180; - int width,height; - int dw=0; - int dh=0; - int index; - CPoint p0[]; - CPoint p1[]; -//--- calculate geometry - width =(m_data_area.Width()<<3)/10; - height=(m_data_area.Height()<<3)/10; - if(IS_SHOW_LEGEND || !IS_SHOW_DESCRIPTORS) - { - if(IS_SHOW_VALUE) - dw=(int)m_max_value_width; - else - { - if(IS_SHOW_PERCENT) - dw=TextWidth("100.00%"); - } - } - else - { - if(IS_SHOW_DESCRIPTORS) - { - if(IS_SHOW_VALUE) - dw=(int)m_max_value_width+TextWidth(" ()"); - else - { - if(IS_SHOW_PERCENT) - dw=TextWidth(" (100.00%)"); - } - dw+=(int)m_max_descr_width; - } - } -//--- pie chart will always be round - width -=2*dw+10; - height-=20; - m_x0=m_data_area.left+(m_data_area.Width()>>1); - m_y0=m_data_area.top+(m_data_area.Height()>>1); - m_r =(((width>height) ? height : width)>>1); -//--- draw pie chart - if(ArrayResize(p0,m_data_total+1)==-1) - return; - if(m_data_total==1) - { - FillCircle(m_x0,m_y0,m_r,m_colors[0]); - Circle(m_x0,m_y0,m_r,m_color_border); - } - else - { - Circle(m_x0,m_y0,m_r,m_color_border); - for(uint i=0;i=m_x0) - { - x=p1[i].x+10; - y=p1[i].y; - index=m_index[i]; - text=LabelMake(m_descriptors[index],m_values[index],false); - if(text!="") - { - Line(p0[i].x,p0[i].y,p1[i].x,p1[i].y,m_color_border); - Line(p1[i].x,p1[i].y,x,y,m_color_border); - TextOut(x+5,y,text,m_color_text,TA_LEFT|TA_VCENTER); - } - } - if(m_data_total!=m_index_size) - { - index=(int)m_data_total-1; - if(p0[index].x>=m_x0) - { - x=p1[index].x+10; - y=p1[index].y; - text=LabelMake("Others",m_others,true); - TextOut(x+5,y,text,m_color_text,TA_LEFT|TA_VCENTER); - } - else - { - x=p1[index].x-10; - y=p1[index].y; - text=LabelMake("Others",m_others,false); - TextOut(x-5,y,text,m_color_text,TA_RIGHT|TA_VCENTER); - } - if(text!="") - { - Line(p0[index].x,p0[index].y,p1[index].x,p1[index].y,m_color_border); - Line(p1[index].x,p1[index].y,x,y,m_color_border); - } - } - ArrayFree(p1); - ArrayFree(p0); - } -//+------------------------------------------------------------------+ -//| Draw pie | -//+------------------------------------------------------------------+ -void CPieChart::DrawPie(double fi3,double fi4,int idx,CPoint &p[],const uint clr) - { -//--- draw arc - Arc(m_x0,m_y0,m_r,m_r,fi3,fi4,p[idx].x,p[idx].y,p[idx+1].x,p[idx+1].y,clr); -//--- variables - int x3=p[idx].x; - int y3=p[idx].y; - int x4=p[idx+1].x; - int y4=p[idx+1].y; -//--- draw radii - if(idx==0) - Line(m_x0,m_y0,x3,y3,clr); - if(idx!=m_data_total-1) - Line(m_x0,m_y0,x4,y4,clr); -//--- fill - double fi=(fi3+fi4)/2; - int xf=m_x0+(int)(0.99*m_r*cos(fi)); - int yf=m_y0-(int)(0.99*m_r*sin(fi)); - Fill(xf,yf,clr); -//--- for small pie - if(fi4-fi3<=M_PI_4) - Line(m_x0,m_y0,xf,yf,clr); - } -//+------------------------------------------------------------------+ -//| Make label for pie | -//+------------------------------------------------------------------+ -string CPieChart::LabelMake(const string text,const double value,const bool to_left) - { - string label=""; -//--- - if(to_left) - { - if(IS_SHOW_LEGEND || !IS_SHOW_DESCRIPTORS) - { - if(IS_SHOW_VALUE) - label=DoubleToString(value,2); - else - { - if(IS_SHOW_PERCENT) - label=DoubleToString(100*value/m_sum,2)+"%"; - } - } - else - { - label=text; - if(IS_SHOW_VALUE) - label+=" ("+DoubleToString(value,2)+")"; - else - { - if(IS_SHOW_PERCENT) - label+=" ("+DoubleToString(100*value/m_sum,2)+"%)"; - } - } - } - else - { - if(IS_SHOW_LEGEND || !IS_SHOW_DESCRIPTORS) - { - if(IS_SHOW_VALUE) - label=DoubleToString(value,2); - else - { - if(IS_SHOW_PERCENT) - label=DoubleToString(100*value/m_sum,2)+"%"; - } - } - else - { - if(IS_SHOW_VALUE) - label="("+DoubleToString(value,2)+") "; - else - { - if(IS_SHOW_PERCENT) - label="("+DoubleToString(100*value/m_sum,2)+"%) "; - } - label+=text; - } - } -//--- - return(label); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/DX/DXBox.mqh b/Include/Canvas/DX/DXBox.mqh deleted file mode 100644 index fb50af5..0000000 --- a/Include/Canvas/DX/DXBox.mqh +++ /dev/null @@ -1,77 +0,0 @@ -//+------------------------------------------------------------------+ -//| DXBox.mqh | -//| Copyright 2019, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2019, MetaQuotes Software Corp." -#property link "https://www.mql5.com" -//--- -#include "DXMesh.mqh" -#include "DXMath.mqh" -#include "DXUtils.mqh" -//+------------------------------------------------------------------+ -//| 3D Box object | -//+------------------------------------------------------------------+ -class CDXBox : public CDXMesh - { -public: - CDXBox(); - ~CDXBox(); - //--- create bon in specified context - bool Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,const DXVector3 &from,const DXVector3 &to); - //--- update box - bool Update(const DXVector3 &from,const DXVector3 &to); - -private: - //--- - void PrepareVertices(const DXVector3 &from,const DXVector3 &to); - }; -//+------------------------------------------------------------------+ -//| Class constructor | -//+------------------------------------------------------------------+ -void CDXBox::CDXBox() : CDXMesh() - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -void CDXBox::~CDXBox(void) - { - } -//+------------------------------------------------------------------+ -//| Create box in specified context | -//+------------------------------------------------------------------+ -bool CDXBox::Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,const DXVector3 &from,const DXVector3 &to) - { -//--- release previous buffers - Shutdown(); -//--- - DXVertex vertices[]; - uint indices[]; -//--- prepare box vertices and indices - DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f); - if(!DXComputeBox(from,to,vertices,indices)) - return(false); - for(int i=0; i - bool Create(int context_handle,const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY) - { - Shutdown(); - m_context=context_handle; - m_handle=DXBufferCreate(m_context,DX_BUFFER_VERTEX,vertices,start,count); - return(m_handle!=INVALID_HANDLE); - } - //+------------------------------------------------------------------+ - //| Render | - //+------------------------------------------------------------------+ - bool Render(uint start=0,uint count=WHOLE_ARRAY) - { - return(DXBufferSet(m_context,m_handle,start,count)); - } - //+------------------------------------------------------------------+ - //| Shutdown | - //+------------------------------------------------------------------+ - void Shutdown(void) - { - //--- relase handle - if(m_handle!=INVALID_HANDLE) - DXRelease(m_handle); - m_handle=INVALID_HANDLE; - } - }; -//+------------------------------------------------------------------+ -//| DX index buffer | -//+------------------------------------------------------------------+ -class CDXIndexBuffer : public CDXHandleShared - { -public: - //+------------------------------------------------------------------+ - //| Destructor | - //+------------------------------------------------------------------+ - virtual ~CDXIndexBuffer(void) - { - Shutdown(); - } - //+------------------------------------------------------------------+ - //| Create index buffer in specified context | - //+------------------------------------------------------------------+ - bool Create(int context_handle,const uint &indices[],uint start=0,uint count=WHOLE_ARRAY) - { - Shutdown(); - m_context=context_handle; - m_handle=DXBufferCreate(m_context,DX_BUFFER_INDEX,indices,start,count); - return(m_handle!=INVALID_HANDLE); - } - //+------------------------------------------------------------------+ - //| Render | - //+------------------------------------------------------------------+ - bool Render(uint start=0,uint count=WHOLE_ARRAY) - { - return(DXBufferSet(m_context,m_handle,start,count)); - } - //+------------------------------------------------------------------+ - //| Shutdown | - //+------------------------------------------------------------------+ - void Shutdown(void) - { - //--- relase handle - if(m_handle!=INVALID_HANDLE) - DXRelease(m_handle); - m_handle=INVALID_HANDLE; - } - }; -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/DX/DXData.mqh b/Include/Canvas/DX/DXData.mqh deleted file mode 100644 index 252803c..0000000 Binary files a/Include/Canvas/DX/DXData.mqh and /dev/null differ diff --git a/Include/Canvas/DX/DXDispatcher.mqh b/Include/Canvas/DX/DXDispatcher.mqh deleted file mode 100644 index 4fc6f71..0000000 --- a/Include/Canvas/DX/DXDispatcher.mqh +++ /dev/null @@ -1,373 +0,0 @@ -//+------------------------------------------------------------------+ -//| DXDispatcher.mqh | -//| Copyright 2019, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2019, MetaQuotes Software Corp." -#property link "https://www.mql5.com" -//--- -#include "DXObjectBase.mqh" -#include "DXData.mqh" -#include "DXBuffers.mqh" -#include "DXInput.mqh" -#include "DXTexture.mqh" -#include "DXShader.mqh" -//--- default shaders -#resource "Shaders/DefaultShaderVertex.hlsl" as string ExtDefaultShaderVertex; -#resource "Shaders/DefaultShaderPixel.hlsl" as string ExtDefaultShaderPixel; -//+------------------------------------------------------------------+ -//| DX dispatcher which holds all resources | -//+------------------------------------------------------------------+ -class CDXDispatcher : public CDXObjectBase - { -protected: - CDXObjectBase m_dx_resources; // DX resources list (Textures, Shaders, etc.) - //--- default shaders - CDXShader* m_default_vs; - CDXShader* m_default_ps; - -public: - CDXDispatcher(void); - ~CDXDispatcher(void); - //--- create/destroy - bool Create(int context); - void Destroy(void); - //--- check resources - void Check(void); - //--- get DX Context Handle - int DXContext(void) const { return(m_context); } - //--- create shaders - CDXShader* ShaderCreateDefault(ENUM_DX_SHADER_TYPE shader_type); - CDXShader* ShaderCreateFromFile(ENUM_DX_SHADER_TYPE shader_type,string path,string entry_point); - CDXShader* ShaderCreateFromSource(ENUM_DX_SHADER_TYPE shader_type,string source,string entry_point); - //--- create buffers - template - CDXVertexBuffer* VertexBufferCreate(const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY); - CDXIndexBuffer* IndexBufferCreate(const uint &indicies[],uint start=0,uint count=WHOLE_ARRAY); - //--- create shader inputs - template - CDXInput* InputCreate(void); - CDXTexture* TextureCreateFromFile(string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0); - CDXTexture* TextureCreateFromData(ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0); - -private: - //--- add resource to list - bool ResourceAdd(CDXObjectBase *resource); - //--- check resources - void ResourcesCheck(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CDXDispatcher::CDXDispatcher(void) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CDXDispatcher::~CDXDispatcher(void) - { - Destroy(); - } -//+------------------------------------------------------------------+ -//| Create | -//+------------------------------------------------------------------+ -bool CDXDispatcher::Create(int context) - { -//--- check if context already exist - if(m_context!=INVALID_HANDLE) - return(false); -//--- save context - m_context=context; -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Destroy | -//+------------------------------------------------------------------+ -void CDXDispatcher::Destroy(void) - { -//--- release default shaders - if(m_default_ps) - { - m_default_ps.Release(); - m_default_ps=NULL; - } - if(m_default_vs) - { - m_default_vs.Release(); - m_default_vs=NULL; - } -//--- release and delete all DX resources - while(m_dx_resources.Next()) - { - CDXHandleShared* resource=(CDXHandleShared*)m_dx_resources.Next(); - resource.Release(); - } -//--- forget context - m_context=INVALID_HANDLE; - } -//+------------------------------------------------------------------+ -//| Check resources | -//+------------------------------------------------------------------+ -void CDXDispatcher::Check(void) - { -//--- - CDXHandleShared* resource=(CDXHandleShared*)m_dx_resources.Next(); -//--- release and delete all DX resources - while(CheckPointer(resource)!=POINTER_INVALID) - { - CDXHandleShared* next=(CDXHandleShared*)resource.Next(); - //--- if references count 1 or less, then only we hold the resource - if(resource.References()<=1) - resource.Release(); - //--- - resource=next; - } - } -//+------------------------------------------------------------------+ -//| Create default shader of specified type | -//+------------------------------------------------------------------+ -CDXShader* CDXDispatcher::ShaderCreateDefault(ENUM_DX_SHADER_TYPE shader_type) - { - switch(shader_type) - { - //--- default pixel shader - case DX_SHADER_PIXEL: - { - if(m_default_ps==NULL) - m_default_ps=ShaderCreateFromSource(DX_SHADER_PIXEL,ExtDefaultShaderPixel,"PSMain"); - return(m_default_ps); - } - //--- default vertex shader - case DX_SHADER_VERTEX: - { - if(m_default_vs==NULL) - { - m_default_vs=ShaderCreateFromSource(DX_SHADER_VERTEX,ExtDefaultShaderVertex,"VSMain"); - if(m_default_vs && !m_default_vs.LayoutSet()) - { - m_default_vs.Release(); - m_default_vs=NULL; - } - } - return(m_default_vs); - } - } -//--- return result - return(NULL); - } -//+------------------------------------------------------------------+ -//| Create new shader of specified type from file | -//+------------------------------------------------------------------+ -CDXShader* CDXDispatcher::ShaderCreateFromFile(ENUM_DX_SHADER_TYPE shader_type,string path,string entry_point) - { -//--- open source file - int file=FileOpen(path,FILE_READ); - if(file==INVALID_HANDLE) - return(NULL); -//--- check file size - uint size=(uint)FileSize(file); - FileClose(file); - if(size>16*1024*1024) - return(NULL); -//--- prepare buffer - char buffer[]; - ArrayResize(buffer,size); -//--- read file into buffer - int read=(int)FileLoad(path,buffer); - if(read<=0) - return(NULL); -//--- convert vuffer to string - string source=CharArrayToString(buffer,0,WHOLE_ARRAY,CP_UTF8); -//--- add shader by source - return(ShaderCreateFromSource(shader_type,source,entry_point)); - } -//+------------------------------------------------------------------+ -//| Create new shader of specified type from source code | -//+------------------------------------------------------------------+ -CDXShader* CDXDispatcher::ShaderCreateFromSource(ENUM_DX_SHADER_TYPE shader_type,string source,string entry_point) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new shader - CDXShader* shader=new CDXShader(); - if(shader==NULL) - return(NULL); -//--- create shader - if(!shader.Create(m_context,shader_type,source,entry_point)) - { - shader.Release(); - return(NULL); - } -//--- add shader to resources list - if(!ResourceAdd(shader)) - { - shader.Release(); - return(NULL); - } -//--- return shader - return(shader); - } -//+------------------------------------------------------------------+ -//| Create vertex buffer | -//+------------------------------------------------------------------+ -template -CDXVertexBuffer* CDXDispatcher::VertexBufferCreate(const TVertex &vertices[],uint start=0,uint count=WHOLE_ARRAY) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new buffer - CDXVertexBuffer* buffer=new CDXVertexBuffer(); - if(buffer==NULL) - return(NULL); -//--- create buffer - if(!buffer.Create(m_context,vertices,start,count)) - { - buffer.Release(); - return(NULL); - } -//--- add buffer to resources list - if(!ResourceAdd(buffer)) - { - buffer.Release(); - return(NULL); - } -//--- return buffer - return(buffer); - } -//+------------------------------------------------------------------+ -//| Create vertex buffer | -//+------------------------------------------------------------------+ -CDXIndexBuffer* CDXDispatcher::IndexBufferCreate(const uint &indicies[],uint start=0,uint count=WHOLE_ARRAY) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new buffer - CDXIndexBuffer* buffer=new CDXIndexBuffer(); - if(buffer==NULL) - return(NULL); -//--- create buffer - if(!buffer.Create(m_context,indicies,start,count)) - { - buffer.Release(); - return(NULL); - } -//--- add buffer to resources list - if(!ResourceAdd(buffer)) - { - buffer.Release(); - return(NULL); - } -//--- return input buffer - return(buffer); - } -//+------------------------------------------------------------------+ -//| Create shader input buffer | -//+------------------------------------------------------------------+ -template -CDXInput* CDXDispatcher::InputCreate(void) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new input buffer - CDXInput* input_buffer=new CDXInput(); - if(input_buffer==NULL) - return(NULL); -//--- create buffer - if(!input_buffer.Create(m_context)) - { - input_buffer.Release(); - return(NULL); - } -//--- add buffer to resources list - if(!ResourceAdd(input_buffer)) - { - input_buffer.Release(); - return(NULL); - } -//--- return shader - return(input_buffer); - } -//+------------------------------------------------------------------+ -//| Create texture from bitmap file | -//+------------------------------------------------------------------+ -CDXTexture* CDXDispatcher::TextureCreateFromFile(string path,uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new texture - CDXTexture* texture=new CDXTexture(); - if(texture==NULL) - return(NULL); -//--- create texture - if(!texture.Create(m_context,path,data_x,data_y,data_width,data_height)) - { - texture.Release(); - return(NULL); - } -//--- add texture to resources list - if(!ResourceAdd(texture)) - { - texture.Release(); - return(NULL); - } -//--- return shader - return(texture); - } -//+------------------------------------------------------------------+ -//| Create texture from raw data, only 32-bit pixel formats supported| -//+------------------------------------------------------------------+ -CDXTexture* CDXDispatcher::TextureCreateFromData(ENUM_DX_FORMAT format,uint width,uint height,const uint &data[],uint data_x=0,uint data_y=0,uint data_width=0,uint data_height=0) - { -//--- check context - if(m_context==INVALID_HANDLE) - return(NULL); -//--- allocate new texture - CDXTexture* texture=new CDXTexture(); - if(texture==NULL) - return(NULL); -//--- create texture - if(!texture.Create(m_context,format,width,height,data,data_x,data_y,data_width,data_height)) - { - texture.Release(); - return(NULL); - } -//--- add texture to resources list - if(!ResourceAdd(texture)) - { - texture.Release(); - return(NULL); - } -//--- return shader - return(texture); - } -//+------------------------------------------------------------------+ -//| Add DX resource | -//+------------------------------------------------------------------+ -bool CDXDispatcher::ResourceAdd(CDXObjectBase *resource) - { -//--- add resource - if(!CheckPointer(resource)) - return(false); -//--- - CDXObjectBase *last=&m_dx_resources; - while(CheckPointer(last.Next())!=POINTER_INVALID) - { - if(last==resource) - return(false); - //--- - last=last.Next(); - } -//--- - resource.Next(NULL); - resource.Prev(last); - last.Next(resource); - return(true); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/DX/DXHandle.mqh b/Include/Canvas/DX/DXHandle.mqh deleted file mode 100644 index 598d529..0000000 Binary files a/Include/Canvas/DX/DXHandle.mqh and /dev/null differ diff --git a/Include/Canvas/DX/DXInput.mqh b/Include/Canvas/DX/DXInput.mqh deleted file mode 100644 index 3907668..0000000 Binary files a/Include/Canvas/DX/DXInput.mqh and /dev/null differ diff --git a/Include/Canvas/DX/DXMath.mqh b/Include/Canvas/DX/DXMath.mqh deleted file mode 100644 index 3598dcf..0000000 --- a/Include/Canvas/DX/DXMath.mqh +++ /dev/null @@ -1,3352 +0,0 @@ -//+------------------------------------------------------------------+ -//| DXMath.mqh | -//| Copyright 2019,MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2019,MetaQuotes Software Corp." -#property link "https://www.mql5.com" -//+------------------------------------------------------------------+ -//| DirectX Math Routines | -//+------------------------------------------------------------------+ -//| Ported from C++ code of ReactOS, written by David Adam | -//| and Tony Wasserka | -//| | -//| https://doxygen.reactos.org/de/d57/ | -//| dll_2directx_2wine_2d3dx9__36_2math_8c_source.html | -//| | -//| Copyright (C) 2007 David Adam | -//| Copyright (C) 2007 Tony Wasserka | -//+------------------------------------------------------------------+ -#define DX_PI 3.1415926535897932384626f -#define DX_PI_DIV2 1.5707963267948966192313f -#define DX_PI_DIV3 1.0471975511965977461542f -#define DX_PI_DIV4 0.7853981633974483096156f -#define DX_PI_DIV6 0.5235987755982988730771f -#define DX_PI_MUL2 6.2831853071795864769253f -#define DXSH_MINORDER 2 -#define DXSH_MAXORDER 6 -//+------------------------------------------------------------------+ -//| Preliminary declarations | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| DXColor | -//+------------------------------------------------------------------+ -struct DXColor; -struct DXPlane; -struct DXVector2; -struct DXVector3; -struct DXVector4; -struct DXMatrix; -struct DXQuaternion; -struct DViewport; -//+------------------------------------------------------------------+ -//| DXColor | -//+------------------------------------------------------------------+ -struct DXColor - { - float r; - float g; - float b; - float a; - //--- constructors - DXColor(void) { r=0.0; g=0.0; b=0.0; a=1.0; } - DXColor(float red,float green,float blue, float alpha) { r=red; g=green; b=blue; a=alpha; } - DXColor(const DXVector4 &v) { r=v.x; g=v.y; b=v.z; a=v.w; } - DXColor(const DXVector3 &v) { r=v.x; g=v.y; b=v.z; a=1.0; } - }; -//+------------------------------------------------------------------+ -//| DXPlane | -//+------------------------------------------------------------------+ -struct DXPlane - { - float a; - float b; - float c; - float d; - }; -//+------------------------------------------------------------------+ -//| DXVector2 | -//+------------------------------------------------------------------+ -struct DXVector2 - { - float x; - float y; - //--- constructors - DXVector2(void) { x=0.0; y=0.0; } - DXVector2(float v) { x=v; y=v; } - DXVector2(float vx,float vy) { x=vx; y=vy; } - DXVector2(const DXVector3 &v) { x=v.x; y=v.y; } - DXVector2(const DXVector4 &v) { x=v.x; y=v.y; } - }; -//+------------------------------------------------------------------+ -//| DXVector3 | -//+------------------------------------------------------------------+ -struct DXVector3 - { - float x; - float y; - float z; - //--- constructors - DXVector3(void) { x=0.0; y=0.0; z=0.0; } - DXVector3(float v) { x=v; y=v; z=v; } - DXVector3(float vx,float vy,float vz) { x=vx; y=vy; z=vz; } - DXVector3(const DXVector2 &v) { x=v.x; y=v.y; z=0.0; } - DXVector3(const DXVector4 &v) { x=v.x; y=v.y; z=v.z; } - }; -//+------------------------------------------------------------------+ -//| DXVector4 | -//+------------------------------------------------------------------+ -struct DXVector4 - { - float x; - float y; - float z; - float w; - //--- constructors - DXVector4(void) { x=0.0; y=0.0; z=0.0; w=1.0; } - DXVector4(float v) { x=v; y=v; z=v; w=v; } - DXVector4(float vx,float vy,float vz,float vw) { x=vx; y=vy; z=vz; w=vw; } - DXVector4(const DXVector2 &v) { x=v.x; y=v.y; z=0.0; w=1.0; } - DXVector4(const DXVector3 &v) { x=v.x; y=v.y; z=v.z; w=1.0; } - }; -//+------------------------------------------------------------------+ -//| DXMatrix | -//+------------------------------------------------------------------+ -struct DXMatrix - { - float m[4][4]; - }; -//+------------------------------------------------------------------+ -//| DXQuaternion | -//+------------------------------------------------------------------+ -struct DXQuaternion - { - float x; - float y; - float z; - float w; - }; -//+------------------------------------------------------------------+ -//| DViewport | -//+------------------------------------------------------------------+ -struct DViewport - { - ulong x; - ulong y; - ulong width; - ulong height; - float minz; - float maxz; - }; - -/* -//--- DXColor functions -void DXColorAdd(DXColor &pout,const DXColor &pc1,const DXColor &pc2); -void DXColorAdjustContrast(DXColor &pout,const DXColor &pc,float s); -void DXColorAdjustSaturation(DXColor &pout,const DXColor &pc,float s); -void DXColorLerp(DXColor &pout,const DXColor &pc1,const DXColor &pc2,float s); -void DXColorModulate(DXColor &pout,const DXColor &pc1,const DXColor &pc2); -void DXColorNegative(DXColor &pout,const DXColor &pc); -void DXColorScale(DXColor &pout,const DXColor &pc,float s); -void DXColorSubtract(DXColor &pout,const DXColor &pc1,const DXColor &pc2); -float DXFresnelTerm(float costheta,float refractionindex); - -//--- DXVector2 functions -void DXVec2Add(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2); -void DXVec2BaryCentric(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2,const DXVector2 &pv3,float f,float g); -void DXVec2CatmullRom(DXVector2 &pout,const DXVector2 &pv0,const DXVector2 &pv1,const DXVector2 &pv2,const DXVector2 &pv3,float s); -float DXVec2CCW(const DXVector2 &pv1,const DXVector2 &pv2); -float DXVec2Dot(const DXVector2 &pv1,const DXVector2 &pv2); -void DXVec2Hermite(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pt1,const DXVector2 &pv2,const DXVector2 &pt2,float s); -float DXVec2Length(const DXVector2 &v); -float DXVec2LengthSq(const DXVector2 &v); -void DXVec2Lerp(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2,float s); -void DXVec2Maximize(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2); -void DXVec2Minimize(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2); -void DXVec2Normalize(DXVector2 &pout,const DXVector2 &pv); -void DXVec2Scale(DXVector2 &pout,const DXVector2 &pv,float s); -void DXVec2Subtract(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2); -void DXVec2Transform(DXVector4 &pout,const DXVector2 &pv,const DXMatrix &pm); -void DXVec2TransformCoord(DXVector2 &pout,const DXVector2 &pv,const DXMatrix &pm); -void DXVec2TransformNormal(DXVector2 &pout,const DXVector2 &pv,const DXMatrix &pm); - -//--- DXVector3 functions -void DXVec3Add(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2); -void DXVec3BaryCentric(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2,const DXVector3 &pv3,float f,float g); -void DXVec3CatmullRom(DXVector3 &pout,const DXVector3 &pv0,const DXVector3 &pv1,const DXVector3 &pv2,const DXVector3 &pv3,float s); -void DXVec3Cross(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2); -float DXVec3Dot(const DXVector3 &pv1,const DXVector3 &pv2); -void DXVec3Hermite(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pt1,const DXVector3 &pv2,const DXVector3 &pt2,float s); -float DXVec3Length(const DXVector3 &pv); -float DXVec3LengthSq(const DXVector3 &pv); -void DXVec3Lerp(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2,float s); -void DXVec3Maximize(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2); -void DXVec3Minimize(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2); -void DXVec3Normalize(DXVector3 &pout,const DXVector3 &pv); -void DXVec3Project(DXVector3 &pout,const DXVector3 &pv,const DViewport &pviewport,const DXMatrix &pprojection,const DXMatrix &pview,const DXMatrix &pworld); -void DXVec3Scale(DXVector3 &pout,const DXVector3 &pv,float s); -void DXVec3Subtract(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2); -void DXVec3Transform(DXVector4 &pout,const DXVector3 &pv,const DXMatrix &pm); -void DXVec3TransformCoord(DXVector3 &pout,const DXVector3 &pv,const DXMatrix &pm); -void DXVec3TransformNormal(DXVector3 &pout,const DXVector3 &pv,const DXMatrix &pm); -void DXVec3Unproject(DXVector3 &out,const DXVector3 &v,const DViewport &viewport,const DXMatrix &projection,const DXMatrix &view,const DXMatrix &world); - -//--- DXVector4 vector functions -void DXVec4Add(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2); -void DXVec4BaryCentric(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2,const DXVector4 &pv3,float f,float g); -void DXVec4CatmullRom(DXVector4 &pout,const DXVector4 &pv0,const DXVector4 &pv1,const DXVector4 &pv2,const DXVector4 &pv3,float s); -void DXVec4Cross(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2,const DXVector4 &pv3); -float DXVec4Dot(const DXVector4 &pv1,const DXVector4 &pv2); -void DXVec4Hermite(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pt1,const DXVector4 &pv2,const DXVector4 &pt2,float s); -float DXVec4Length(const DXVector4 &pv); -float DXVec4LengthSq(const DXVector4 &pv); -void DXVec4Lerp(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2,float s); -void DXVec4Maximize(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2); -void DXVec4Minimize(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2); -void DXVec4Normalize(DXVector4 &pout,const DXVector4 &pv); -void DXVec4Scale(DXVector4 &pout,const DXVector4 &pv,float s); -void DXVec4Subtract(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2); -void DXVec4Transform(DXVector4 &pout,const DXVector4 &pv,const DXMatrix &pm); - -//---DXQuaternion functions -void DXQuaternionBaryCentric(DXQuaternion &pout,DXQuaternion &pq1,DXQuaternion &pq2,DXQuaternion &pq3,float f,float g); -void DXQuaternionConjugate(DXQuaternion &pout,const DXQuaternion &pq); -float DXQuaternionDot(DXQuaternion &a,DXQuaternion &b); -void DXQuaternionExp(DXQuaternion &out,const DXQuaternion &q); -void DXQuaternionIdentity(DXQuaternion &out); -bool DXQuaternionIsIdentity(DXQuaternion &pq); -float DXQuaternionLength(const DXQuaternion &pq); -float DXQuaternionLengthSq(const DXQuaternion &pq); -void DXQuaternionInverse(DXQuaternion &pout,const DXQuaternion &pq); -void DXQuaternionLn(DXQuaternion &out,const DXQuaternion &q); -void DXQuaternionMultiply(DXQuaternion &pout,const DXQuaternion &pq1,const DXQuaternion &pq2); -void DXQuaternionNormalize(DXQuaternion &out,const DXQuaternion &q); -void DXQuaternionRotationAxis(DXQuaternion &out,const DXVector3 &v,float angle); -void DXQuaternionRotationMatrix(DXQuaternion &out,const DXMatrix &m); -void DXQuaternionRotationYawPitchRoll(DXQuaternion &out,float yaw,float pitch,float roll); -void DXQuaternionSlerp(DXQuaternion &out,DXQuaternion &q1,DXQuaternion &q2,float t); -void DXQuaternionSquad(DXQuaternion &pout,DXQuaternion &pq1,DXQuaternion &pq2,DXQuaternion &pq3,DXQuaternion &pq4,float t); -void DXQuaternionSquadSetup(DXQuaternion &paout,DXQuaternion &pbout,DXQuaternion &pcout,DXQuaternion &pq0,DXQuaternion &pq1,DXQuaternion &pq2,DXQuaternion &pq3); -void DXQuaternionToAxisAngle(const DXQuaternion &pq,DXVector3 &paxis,float &pangle); -DXQuaternion add_diff(const DXQuaternion &q1,const DXQuaternion &q2,const float add); - -//--- DXMatrix functions -void DXMatrixIdentity(DXMatrix &out); -bool DXMatrixIsIdentity(DXMatrix &pm); -void DXMatrixAffineTransformation(DXMatrix &out,float scaling,const DXVector3 &rotationcenter,const DXQuaternion &rotation,const DXVector3 &translation); -void DXMatrixAffineTransformation2D(DXMatrix &out,float scaling,const DXVector2 &rotationcenter,float rotation,const DXVector2 &translation); -int DXMatrixDecompose(DXVector3 &poutscale,DXQuaternion &poutrotation,DXVector3 &pouttranslation,const DXMatrix &pm); -float DXMatrixDeterminant(const DXMatrix &pm); -void DXMatrixInverse(DXMatrix &pout,float &pdeterminant,const DXMatrix &pm); -void DXMatrixLookAtLH(DXMatrix &out,const DXVector3 &eye,const DXVector3 &at,const DXVector3 &up); -void DXMatrixLookAtRH(DXMatrix &out,const DXVector3 &eye,const DXVector3 &at,const DXVector3 &up); -void DXMatrixMultiply(DXMatrix &pout,const DXMatrix &pm1,const DXMatrix &pm2); -void DXMatrixMultiplyTranspose(DXMatrix &pout,const DXMatrix &pm1,const DXMatrix &pm2); -void DXMatrixOrthoLH(DXMatrix &pout,float w,float h,float zn,float zf); -void DXMatrixOrthoOffCenterLH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf); -void DXMatrixOrthoOffCenterRH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf); -void DXMatrixOrthoRH(DXMatrix &pout,float w,float h,float zn,float zf); -void DXMatrixPerspectiveFovLH(DXMatrix &pout,float fovy,float aspect,float zn,float zf); -void DXMatrixPerspectiveFovRH(DXMatrix &pout,float fovy,float aspect,float zn,float zf); -void DXMatrixPerspectiveLH(DXMatrix &pout,float w,float h,float zn,float zf); -void DXMatrixPerspectiveOffCenterLH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf); -void DXMatrixPerspectiveOffCenterRH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf); -void DXMatrixPerspectiveRH(DXMatrix &pout,float w,float h,float zn,float zf); -void DXMatrixReflect(DXMatrix &pout,const DXPlane &pplane); -void DXMatrixRotationAxis(DXMatrix &out,const DXVector3 &v,float angle); -void DXMatrixRotationQuaternion(DXMatrix &pout,const DXQuaternion &pq); -void DXMatrixRotationX(DXMatrix &pout,float angle); -void DXMatrixRotationY(DXMatrix &pout,float angle); -void DXMatrixRotationYawPitchRoll(DXMatrix &out,float yaw,float pitch,float roll); -void DXMatrixRotationZ(DXMatrix &pout,float angle); -void DXMatrixScaling(DXMatrix &pout,float sx,float sy,float sz); -void DXMatrixShadow(DXMatrix &pout,const DXVector4 &plight,const DXPlane &pplane); -void DXMatrixTransformation(DXMatrix &pout,const DXVector3 &pscalingcenter,const DXQuaternion &pscalingrotation,const DXVector3 &pscaling,const DXVector3 &protationcenter,const DXQuaternion &protation,const DXVector3 &ptranslation); -void DXMatrixTransformation2D(DXMatrix &pout,const DXVector2 &pscalingcenter,float scalingrotation,const DXVector2 &pscaling,const DXVector2 &protationcenter,float rotation,const DXVector2 &ptranslation); -void DXMatrixTranslation(DXMatrix &pout,float x,float y,float z); -void DXMatrixTranspose(DXMatrix &pout,const DXMatrix &pm); - -//--- DXPlane functions | -float DXPlaneDot(const DXPlane &p1,const DXVector4 &p2); -float DXPlaneDotCoord(const DXPlane &pp,const DXVector4 &pv); -float DXPlaneDotNormal(const DXPlane &pp,const DXVector4 &pv); -void DXPlaneFromPointNormal(DXPlane &pout,const DXVector3 &pvpoint,const DXVector3 &pvnormal); -void DXPlaneFromPoints(DXPlane &pout,const DXVector3 &pv1,const DXVector3 &pv2,const DXVector3 &pv3); -void DXPlaneIntersectLine(DXVector3 &pout,const DXPlane &pp,const DXVector3 &pv1,const DXVector3 &pv2); -void DXPlaneNormalize(DXPlane &out,const DXPlane &p); -void DXPlaneScale(DXPlane &pout,const DXPlane &p,float s); -void DXPlaneTransform(DXPlane &pout,const DXPlane &pplane,const DXMatrix &pm); - -//---- spherical harmonic functions -void DXSHAdd(float &out[],int order,const float &a[],const float &b[]); -float DXSHDot(int order,const float &a[],const float &b[]); -int DXSHEvalConeLight(int order,const DXVector3 &dir,float radius,float Rintensity,float Gintensity,float Bintensity,float &rout[],float &gout[],float &bout[]); -void DXSHEvalDirection(float &out[],int order,const DXVector3 &dir); -int DXSHEvalDirectionalLight(int order,const DXVector3 &dir,float Rintensity,float Gintensity,float Bintensity,float &rout[],float &gout[],float &bout[]); -int DXSHEvalHemisphereLight(int order,const DXVector3 &dir,DXColor &top,DXColor &bottom,float &rout[],float &gout[],float &bout[]); -int DXSHEvalSphericalLight(int order,const DXVector3 &dir,float radius,float Rintensity,float Gintensity,float Bintensity,float &rout[],float &gout[],float &bout[]); -void DXSHMultiply2(float &out[],const float &a[],const float &b[]); -void DXSHMultiply3(float &out[],const float &a[],const float &b[]); -void DXSHMultiply4(float &out[],const float &a[],const float &b[]); -void DXSHRotate(float &out[],int order,const DXMatrix &matrix,const float &in[]); -void DXSHRotateZ(float &out[],int order,float angle,const float &in[]); -void DXSHScale(float &out[],int order,const float &a[],const float scale); - -//--- scalar functions -float DXScalarLerp(const float val1,const float val2,float s) -float DXScalarBiasScale(const float val,const float bias,const float scale) -*/ - -//+------------------------------------------------------------------+ -//| Adds two color values together to create a new color value. | -//+------------------------------------------------------------------+ -void DXColorAdd(DXColor &pout,const DXColor &pc1,const DXColor &pc2) - { - pout.r = pc1.r + pc2.r; - pout.g = pc1.g + pc2.g; - pout.b = pc1.b + pc2.b; - pout.a = pc1.a + pc2.a; - } -//+------------------------------------------------------------------+ -//| Adjusts the contrast value of a color. | -//+------------------------------------------------------------------+ -//| The input alpha channel is copied, unmodified, | -//| to the output alpha channel. | -//| | -//| This function interpolates the red,green,and blue color | -//| components of a DXColor structure between fifty percent gray | -//| and a specified contrast value,as shown in the following example.| -//| | -//| pout.r = 0.5f + s*(pc.r - 0.5f); | -//| | -//| If s is greater than 0 and less than 1,the contrast is decreased.| -//| If s is greater than 1, the contrast is increased. | -//+------------------------------------------------------------------+ -void DXColorAdjustContrast(DXColor &pout,const DXColor &pc,float s) - { - pout.r = 0.5f + s*(pc.r - 0.5f); - pout.g = 0.5f + s*(pc.g - 0.5f); - pout.b = 0.5f + s*(pc.b - 0.5f); - pout.a = pc.a; - } -//+------------------------------------------------------------------+ -//| Adjusts the saturation value of a color. | -//+------------------------------------------------------------------+ -//| The input alpha channel is copied, unmodified, | -//| to the output alpha channel. | -//| | -//| This function interpolates the red, green, and blue color | -//| components of a DXColor structure between an unsaturated color | -//| and a color, as shown in the following example. | -//| | -//| Approximate values for each component's contribution to | -//| luminance. Based upon the NTSC standard described in | -//| ITU-R Recommendation BT.709. | -//| float grey = pc.r*0.2125f + pc.g*0.7154f + pc.b*0.0721f; | -//| | -//| pout.r = grey + s*(pc.r - grey); | -//| If s is greater than 0 and less than 1, the saturation is | -//| decreased. If s is greater than 1, the saturation is increased. | -//| | -//| The grayscale color is computed as: | -//| r = g = b = 0.2125*r + 0.7154*g + 0.0721*b | -//+------------------------------------------------------------------+ -void DXColorAdjustSaturation(DXColor &pout,const DXColor &pc,float s) - { - float grey = pc.r*0.2125f + pc.g*0.7154f + pc.b*0.0721f; - pout.r = grey + s*(pc.r - grey); - pout.g = grey + s*(pc.g - grey); - pout.b = grey + s*(pc.b - grey); - pout.a = pc.a; - } -//+------------------------------------------------------------------+ -//| Uses linear interpolation to create a color value. | -//+------------------------------------------------------------------+ -//| This function interpolates the red, green, blue, and alpha | -//| components of a DXColor structure between two colors, as shown | -//| in the following example. | -//| | -//| pout.r = pC1.r + s * (pC2.r - pC1.r); | -//| | -//| If you are linearly interpolating between the colors A and B, | -//| and s is 0, the resulting color is A. | -//| If s is 1, the resulting color is color B. | -//+------------------------------------------------------------------+ -void DXColorLerp(DXColor &pout,const DXColor &pc1,const DXColor &pc2,float s) - { - pout.r = (1-s)*pc1.r + s*pc2.r; - pout.g = (1-s)*pc1.g + s*pc2.g; - pout.b = (1-s)*pc1.b + s*pc2.b; - pout.a = (1-s)*pc1.a + s*pc2.a; - } -//+------------------------------------------------------------------+ -//| Blends two colors. | -//+------------------------------------------------------------------+ -//| This function blends together two colors by multiplying matching | -//| color components, as shown in the following example. | -//| pout.r = pC1.r * pC2.r; | -//+------------------------------------------------------------------+ -void DXColorModulate(DXColor &pout,const DXColor &pc1,const DXColor &pc2) - { - pout.r = pc1.r*pc2.r; - pout.g = pc1.g*pc2.g; - pout.b = pc1.b*pc2.b; - pout.a = pc1.a*pc2.a; - } -//+------------------------------------------------------------------+ -//| Creates the negative color value of a color value. | -//+------------------------------------------------------------------+ -//| The input alpha channel is copied, unmodified, to the output | -//| alpha channel. | -//| This function returns the negative color value by subtracting 1.0| -//| from the color components of the DXColor structure, | -//| as shown in the following example. | -//| pout.r = 1.0f - pc.r; | -//+------------------------------------------------------------------+ -void DXColorNegative(DXColor &pout,const DXColor &pc) - { - pout.r = 1.0f - pc.r; - pout.g = 1.0f - pc.g; - pout.b = 1.0f - pc.b; - pout.a = pc.a; - } -//+------------------------------------------------------------------+ -//| Scales a color value. | -//+------------------------------------------------------------------+ -//| This function computes the scaled color value by multiplying | -//| the color components of the DXColor structure by the specified | -//| scale factor, as shown in the following example. | -//| pOut.r = pC.r*s; | -//+------------------------------------------------------------------+ -void DXColorScale(DXColor &pout,const DXColor &pc,float s) - { - pout.r = s*pc.r; - pout.g = s*pc.g; - pout.b = s*pc.b; - pout.a = s*pc.a; - } -//+------------------------------------------------------------------+ -//| Subtracts two color values to create a new color value. | -//+------------------------------------------------------------------+ -void DXColorSubtract(DXColor &pout,const DXColor &pc1,const DXColor &pc2) - { - pout.r = pc1.r - pc2.r; - pout.g = pc1.g - pc2.g; - pout.b = pc1.b - pc2.b; - pout.a = pc1.a - pc2.a; - } -//+------------------------------------------------------------------+ -//| Calculate the Fresnel term. | -//+------------------------------------------------------------------+ -//| To find the Fresnel term (F): | -//| If A is angle of incidence and B is the angle of refraction, | -//| then | -//| F = 0.5*[tan2(A - B)/tan2(A + B) + sin2(A - B)/sin2(A + B)] | -//| = 0.5*sin2(A - B)/sin2(A + B)*[cos2(A + B)/cos2(A - B) + 1] | -//| | -//| Let r = sina(A)/sin(B) (the relative refractive index) | -//| Let c = cos(A) | -//| Let g = (r2 + c2 - 1)1/2 | -//| | -//| Then,expanding using the trig identities and simplifying, | -//| you get: | -//| F = 0.5*(g + c)2/(g - c)2*([c(g + c)-1]2/[c(g - c) + 1]2 + 1) | -//+------------------------------------------------------------------+ -float DXFresnelTerm(float costheta,float refractionindex) - { - float g = (float)sqrt(refractionindex*refractionindex + costheta*costheta - 1.0f); - float a = g + costheta; - float d = g - costheta; - float result = (costheta*a - 1.0f)*(costheta*a - 1.0f)/((costheta*d + 1.0f)*(costheta*d + 1.0f)) + 1.0f; - result *= 0.5f*d*d/(a*a); -//--- - return(result); - } -//+------------------------------------------------------------------+ -//| Adds two 2D vectors. | -//+------------------------------------------------------------------+ -void DXVec2Add(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2) - { - pout.x = pv1.x + pv2.x; - pout.y = pv1.y + pv2.y; - } -//+------------------------------------------------------------------+ -//| Returns a point in Barycentric coordinates, | -//| using the specified 2D vectors. | -//+------------------------------------------------------------------+ -void DXVec2BaryCentric(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2,const DXVector2 &pv3,float f,float g) - { - pout.x = (1.0f-f-g)*(pv1.x) + f*(pv2.x) + g*(pv3.x); - pout.y = (1.0f-f-g)*(pv1.y) + f*(pv2.y) + g*(pv3.y); - } -//+------------------------------------------------------------------+ -//| Performs a Catmull-Rom interpolation, | -//| using the specified 2D vectors. | -//+------------------------------------------------------------------+ -void DXVec2CatmullRom(DXVector2 &pout,const DXVector2 &pv0,const DXVector2 &pv1,const DXVector2 &pv2,const DXVector2 &pv3,float s) - { - pout.x = 0.5f*(2.0f*pv1.x + (pv2.x-pv0.x)*s + (2.0f*pv0.x - 5.0f*pv1.x + 4.0f*pv2.x - pv3.x)*s*s + (pv3.x - 3.0f*pv2.x + 3.0f*pv1.x - pv0.x)*s*s*s); - pout.y = 0.5f*(2.0f*pv1.y + (pv2.y-pv0.y)*s + (2.0f*pv0.y - 5.0f*pv1.y + 4.0f*pv2.y - pv3.y)*s*s + (pv3.y - 3.0f*pv2.y + 3.0f*pv1.y - pv0.y)*s*s*s); - } -//+------------------------------------------------------------------+ -//| Returns the z-component by taking the cross product | -//| of two 2D vectors. | -//+------------------------------------------------------------------+ -float DXVec2CCW(const DXVector2 &pv1,const DXVector2 &pv2) - { - return(pv1.x*pv2.y - pv1.y*pv2.x); - } -//+------------------------------------------------------------------+ -//| Determines the dot product of two 2D vectors. | -//+------------------------------------------------------------------+ -float DXVec2Dot(const DXVector2 &pv1,const DXVector2 &pv2) - { - return(pv1.x*pv2.x + pv1.y*pv2.y); - } -//+------------------------------------------------------------------+ -//| Performs a Hermite spline interpolation, | -//| using the specified 2D vectors. | -//+------------------------------------------------------------------+ -void DXVec2Hermite(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pt1,const DXVector2 &pv2,const DXVector2 &pt2,float s) - { -//--- prepare coefficients - float h1 = 2.0f*s*s*s - 3.0f*s*s + 1.0f; - float h2 = s*s*s - 2.0f*s*s + s; - float h3 = -2.0f*s*s*s + 3.0f*s*s; - float h4 = s*s*s - s*s; -//--- calculate interpolated point - pout.x = h1*pv1.x + h2*pt1.x + h3*pv2.x + h4*pt2.x; - pout.y = h1*pv1.y + h2*pt1.y + h3*pv2.y + h4*pt2.y; - } -//+------------------------------------------------------------------+ -//| Returns the length of a 2D vector. | -//+------------------------------------------------------------------+ -float DXVec2Length(const DXVector2 &v) - { - return((float)sqrt(v.x*v.x + v.y*v.y)); - } -//+------------------------------------------------------------------+ -//| Returns the square of the length of a 2D vector. | -//+------------------------------------------------------------------+ -float DXVec2LengthSq(const DXVector2 &v) - { - return((float)(v.x*v.x + v.y*v.y)); - } -//+------------------------------------------------------------------+ -//| Performs a linear interpolation between two 2D vectors. | -//+------------------------------------------------------------------+ -void DXVec2Lerp(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2,float s) - { - pout.x = (1.0f-s)*pv1.x + s*pv2.x; - pout.y = (1.0f-s)*pv1.y + s*pv2.y; - } -//+------------------------------------------------------------------+ -//| Returns a 2D vector that is made up of the largest components | -//| of two 2D vectors. | -//+------------------------------------------------------------------+ -void DXVec2Maximize(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2) - { - pout.x = (float)fmax(pv1.x,pv2.x); - pout.y = (float)fmax(pv1.y,pv2.y); - } -//+------------------------------------------------------------------+ -//| Returns a 2D vector that is made up of the smallest components | -//| of two 2D vectors. | -//+------------------------------------------------------------------+ -void DXVec2Minimize(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2) - { - pout.x = (float)fmin(pv1.x,pv2.x); - pout.y = (float)fmin(pv1.y,pv2.y); - } -//+------------------------------------------------------------------+ -//| Returns the normalized version of a 2D vector. | -//+------------------------------------------------------------------+ -void DXVec2Normalize(DXVector2 &pout,const DXVector2 &pv) - { -//--- calculate length - float norm = DXVec2Length(pv); - if(!norm) - { - pout.x = 0.0f; - pout.y = 0.0f; - } - else - { - pout.x = pv.x/norm; - pout.y = pv.y/norm; - } - } -//+------------------------------------------------------------------+ -//| Scales a 2D vector. | -//+------------------------------------------------------------------+ -void DXVec2Scale(DXVector2 &pout,const DXVector2 &pv,float s) - { - pout.x = s*pv.x; - pout.y = s*pv.y; - } -//+------------------------------------------------------------------+ -//| DXVec3Subtract | -//+------------------------------------------------------------------+ -void DXVec2Subtract(DXVector2 &pout,const DXVector2 &pv1,const DXVector2 &pv2) - { - pout.x = pv1.x - pv2.x; - pout.y = pv1.y - pv2.y; - } -//+------------------------------------------------------------------+ -//| Transforms a 2D vector by a given matrix. | -//| This function transforms the vector pv(x,y,0,1) by the matrix pm.| -//+------------------------------------------------------------------+ -void DXVec2Transform(DXVector4 &pout,const DXVector2 &pv,const DXMatrix &pm) - { - DXVector4 out; - out.x = pm.m[0][0]*pv.x + pm.m[1][0]*pv.y + pm.m[3][0]; - out.y = pm.m[0][1]*pv.x + pm.m[1][1]*pv.y + pm.m[3][1]; - out.z = pm.m[0][2]*pv.x + pm.m[1][2]*pv.y + pm.m[3][2]; - out.w = pm.m[0][3]*pv.x + pm.m[1][3]*pv.y + pm.m[3][3]; - pout = out; - } -//+------------------------------------------------------------------+ -//| Transforms a 2D vector by a given matrix, | -//| projecting the result back into w = 1. | -//| This function transforms the vector pv(x,y,0,1) by the matrix pm.| -//+------------------------------------------------------------------+ -void DXVec2TransformCoord(DXVector2 &pout,const DXVector2 &pv,const DXMatrix &pm) - { - float norm = pm.m[0][3]*pv.x + pm.m[1][3]*pv.y + pm.m[3][3]; - if(norm) - { - pout.x = (pm.m[0][0]*pv.x + pm.m[1][0]*pv.y + pm.m[3][0])/norm; - pout.y = (pm.m[0][1]*pv.x + pm.m[1][1]*pv.y + pm.m[3][1])/norm; - } - else - { - pout.x = 0.0f; - pout.y = 0.0f; - } - } -//+------------------------------------------------------------------+ -//| Transforms the 2D vector normal by the given matrix. | -//+------------------------------------------------------------------+ -void DXVec2TransformNormal(DXVector2 &pout,const DXVector2 &pv,const DXMatrix &pm) - { - pout.x = pm.m[0][0]*pv.x + pm.m[1][0]*pv.y; - pout.y = pm.m[0][1]*pv.x + pm.m[1][1]*pv.y; - } -//+------------------------------------------------------------------+ -//| Adds two 3D vectors. | -//+------------------------------------------------------------------+ -void DXVec3Add(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2) - { - pout.x = pv1.x + pv2.x; - pout.y = pv1.y + pv2.y; - pout.z = pv1.z + pv2.z; - } -//+------------------------------------------------------------------+ -//| Returns a point in Barycentric coordinates, | -//| using the specified 3D vectors. | -//+------------------------------------------------------------------+ -void DXVec3BaryCentric(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2,const DXVector3 &pv3,float f,float g) - { - pout.x = (1.0f-f-g)*pv1.x + f*pv2.x + g*pv3.x; - pout.y = (1.0f-f-g)*pv1.y + f*pv2.y + g*pv3.y; - pout.z = (1.0f-f-g)*pv1.z + f*pv2.z + g*pv3.z; - } -//+------------------------------------------------------------------+ -//| Performs a Catmull-Rom interpolation, | -//| using the specified 3D vectors. | -//+------------------------------------------------------------------+ -void DXVec3CatmullRom(DXVector3 &pout,const DXVector3 &pv0,const DXVector3 &pv1,const DXVector3 &pv2,const DXVector3 &pv3,float s) - { - pout.x = 0.5f*(2.0f*pv1.x + (pv2.x - pv0.x)*s + (2.0f*pv0.x - 5.0f*pv1.x + 4.0f*pv2.x - pv3.x)*s*s + (pv3.x - 3.0f*pv2.x + 3.0f*pv1.x - pv0.x)*s*s*s); - pout.y = 0.5f*(2.0f*pv1.y + (pv2.y - pv0.y)*s + (2.0f*pv0.y - 5.0f*pv1.y + 4.0f*pv2.y - pv3.y)*s*s + (pv3.y - 3.0f*pv2.y + 3.0f*pv1.y - pv0.y)*s*s*s); - pout.z = 0.5f*(2.0f*pv1.z + (pv2.z - pv0.z)*s + (2.0f*pv0.z - 5.0f*pv1.z + 4.0f*pv2.z - pv3.z)*s*s + (pv3.z - 3.0f*pv2.z + 3.0f*pv1.z - pv0.z)*s*s*s); - } -//+------------------------------------------------------------------+ -//| Determines the cross-product of two 3D vectors. | -//+------------------------------------------------------------------+ -void DXVec3Cross(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2) - { - pout.x = pv1.y*pv2.z - pv1.z*pv2.y; - pout.y = pv1.z*pv2.x - pv1.x*pv2.z; - pout.z = pv1.x*pv2.y - pv1.y*pv2.x; - } -//+------------------------------------------------------------------+ -//| Determines the dot product of two 3D vectors. | -//+------------------------------------------------------------------+ -float DXVec3Dot(const DXVector3 &pv1,const DXVector3 &pv2) - { - return(pv1.x*pv2.x + pv1.y*pv2.y + pv1.z*pv2.z); - } -//+------------------------------------------------------------------+ -//| Performs a Hermite spline interpolation, | -//| using the specified 3D vectors. | -//+------------------------------------------------------------------+ -void DXVec3Hermite(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pt1,const DXVector3 &pv2,const DXVector3 &pt2,float s) - { - float h1 = 2.0f*s*s*s - 3.0f*s*s + 1.0f; - float h2 = s*s*s - 2.0f*s*s + s; - float h3 = -2.0f*s*s*s + 3.0f*s*s; - float h4 = s*s*s - s*s; -//--- calculate interpolated coordinates - pout.x = h1*pv1.x + h2*pt1.x + h3*pv2.x + h4*pt2.x; - pout.y = h1*pv1.y + h2*pt1.y + h3*pv2.y + h4*pt2.y; - pout.z = h1*pv1.z + h2*pt1.z + h3*pv2.z + h4*pt2.z; - } -//+------------------------------------------------------------------+ -//| Returns the length of a 3D vector. | -//+------------------------------------------------------------------+ -float DXVec3Length(const DXVector3 &pv) - { - return((float)sqrt(pv.x*pv.x + pv.y*pv.y + pv.z*pv.z)); - } -//+------------------------------------------------------------------+ -//| Returns the square of the length of a 3D vector. | -//+------------------------------------------------------------------+ -float DXVec3LengthSq(const DXVector3 &pv) - { - return((float)(pv.x*pv.x + pv.y*pv.y + pv.z*pv.z)); - } -//+------------------------------------------------------------------+ -//| Performs a linear interpolation between two 3D vectors. | -//+------------------------------------------------------------------+ -void DXVec3Lerp(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2,float s) - { - pout.x = (1.0f-s)*pv1.x + s*pv2.x; - pout.y = (1.0f-s)*pv1.y + s*pv2.y; - pout.z = (1.0f-s)*pv1.z + s*pv2.z; - } -//+------------------------------------------------------------------+ -//| Returns a 3D vector that is made up of the largest components | -//| of two 3D vectors. | -//+------------------------------------------------------------------+ -void DXVec3Maximize(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2) - { - pout.x = (float)fmax(pv1.x,pv2.x); - pout.y = (float)fmax(pv1.y,pv2.y); - pout.z = (float)fmax(pv1.z,pv2.z); - } -//+------------------------------------------------------------------+ -//| Returns a 3D vector that is made up of the smallest components | -//| of two 3D vectors. | -//+------------------------------------------------------------------+ -void DXVec3Minimize(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2) - { - pout.x = (float)fmin(pv1.x,pv2.x); - pout.y = (float)fmin(pv1.y,pv2.y); - pout.z = (float)fmin(pv1.z,pv2.z); - } -//+------------------------------------------------------------------+ -//| Returns the normalized version of a 3D vector. | -//+------------------------------------------------------------------+ -void DXVec3Normalize(DXVector3 &pout,const DXVector3 &pv) - { -//--- calculate length - float norm = DXVec3Length(pv); - if(!norm) - { - pout.x = 0.0f; - pout.y = 0.0f; - pout.z = 0.0f; - } - else - { - pout.x = pv.x/norm; - pout.y = pv.y/norm; - pout.z = pv.z/norm; - } - } -//+------------------------------------------------------------------+ -//| Projects a 3D vector from object space into screen space. | -//+------------------------------------------------------------------+ -void DXVec3Project(DXVector3 &pout,const DXVector3 &pv,const DViewport &pviewport,const DXMatrix &pprojection,const DXMatrix &pview,const DXMatrix &pworld) - { - DXMatrix m; - DXMatrixIdentity(m); -//--- pworld - DXMatrixMultiply(m,m,pworld); -//--- pview - DXMatrixMultiply(m,m,pview); -//--- pprojection - DXMatrixMultiply(m,m,pprojection); - DXVec3TransformCoord(pout,pv,m); -//---pviewport - pout.x = pviewport.x + (1.0f + pout.x)*pviewport.width/2.0f; - pout.y = pviewport.y + (1.0f - pout.y)*pviewport.height/2.0f; - pout.z = pviewport.minz + pout.z*(pviewport.maxz - pviewport.minz); - } -//+------------------------------------------------------------------+ -//| Scales a 3D vector. | -//+------------------------------------------------------------------+ -void DXVec3Scale(DXVector3 &pout,const DXVector3 &pv,float s) - { - pout.x = s*pv.x; - pout.y = s*pv.y; - pout.z = s*pv.z; - } -//+------------------------------------------------------------------+ -//| Subtracts two 3D vectors. | -//+------------------------------------------------------------------+ -void DXVec3Subtract(DXVector3 &pout,const DXVector3 &pv1,const DXVector3 &pv2) - { - pout.x = pv1.x - pv2.x; - pout.y = pv1.y - pv2.y; - pout.z = pv1.z - pv2.z; - } -//+------------------------------------------------------------------+ -//| Transforms vector (x,y,z,1) by a given matrix. | -//+------------------------------------------------------------------+ -void DXVec3Transform(DXVector4 &pout,const DXVector3 &pv,const DXMatrix &pm) - { - DXVector4 out; -//--- - out.x = pm.m[0][0]*pv.x + pm.m[1][0]*pv.y + pm.m[2][0]*pv.z + pm.m[3][0]; - out.y = pm.m[0][1]*pv.x + pm.m[1][1]*pv.y + pm.m[2][1]*pv.z + pm.m[3][1]; - out.z = pm.m[0][2]*pv.x + pm.m[1][2]*pv.y + pm.m[2][2]*pv.z + pm.m[3][2]; - out.w = pm.m[0][3]*pv.x + pm.m[1][3]*pv.y + pm.m[2][3]*pv.z + pm.m[3][3]; - pout = out; - } -//+------------------------------------------------------------------+ -//| Transforms a 3D vector by a given matrix, | -//| projecting the result back into w = 1. | -//+------------------------------------------------------------------+ -void DXVec3TransformCoord(DXVector3 &pout,const DXVector3 &pv,const DXMatrix &pm) - { - float norm = pm.m[0][3]*pv.x + pm.m[1][3]*pv.y + pm.m[2][3]*pv.z + pm.m[3][3]; -//--- - if(norm) - { - pout.x = (pm.m[0][0]*pv.x + pm.m[1][0]*pv.y + pm.m[2][0]*pv.z + pm.m[3][0])/norm; - pout.y = (pm.m[0][1]*pv.x + pm.m[1][1]*pv.y + pm.m[2][1]*pv.z + pm.m[3][1])/norm; - pout.z = (pm.m[0][2]*pv.x + pm.m[1][2]*pv.y + pm.m[2][2]*pv.z + pm.m[3][2])/norm; - } - else - { - pout.x = 0.0f; - pout.y = 0.0f; - pout.z = 0.0f; - } - } -//+------------------------------------------------------------------+ -//| Transforms the 3D vector normal by the given matrix. | -//+------------------------------------------------------------------+ -void DXVec3TransformNormal(DXVector3 &pout,const DXVector3 &pv,const DXMatrix &pm) - { - pout.x = pm.m[0][0]*pv.x + pm.m[1][0]*pv.y + pm.m[2][0]*pv.z; - pout.y = pm.m[0][1]*pv.x + pm.m[1][1]*pv.y + pm.m[2][1]*pv.z; - pout.z = pm.m[0][2]*pv.x + pm.m[1][2]*pv.y + pm.m[2][2]*pv.z; - } -//+------------------------------------------------------------------+ -//| Projects a vector from screen space into object space. | -//+------------------------------------------------------------------+ -void DXVec3Unproject(DXVector3 &out,const DXVector3 &v,const DViewport &viewport,const DXMatrix &projection,const DXMatrix &view,const DXMatrix &world) - { - DXMatrix m; - DXMatrixIdentity(m); -//--- world - DXMatrixMultiply(m,m,world); -//--- view - DXMatrixMultiply(m,m,view); -//--- projection - DXMatrixMultiply(m,m,projection); -//--- calculate inverse matrix - float det=0.0f; - DXMatrixInverse(m,det,m); - out = v; -//--- viewport - out.x = 2.0f*(out.x - viewport.x)/viewport.width - 1.0f; - out.y = 1.0f - 2.0f*(out.y - viewport.y)/viewport.height; - out.z = (out.z - viewport.minz)/(viewport.maxz - viewport.minz); -//--- - DXVec3TransformCoord(out,out,m); - } -//+------------------------------------------------------------------+ -//| Adds two 4D vectors. | -//+------------------------------------------------------------------+ -void DXVec4Add(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2) - { - pout.x = pv1.x + pv2.x; - pout.y = pv1.y + pv2.y; - pout.z = pv1.z + pv2.z; - pout.w = pv1.w + pv2.w; - } -//+------------------------------------------------------------------+ -//| Returns a point in Barycentric coordinates, | -//| using the specified 4D vectors. | -//+------------------------------------------------------------------+ -void DXVec4BaryCentric(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2,const DXVector4 &pv3,float f,float g) - { - pout.x = (1.0f-f-g)*(pv1.x) + f*(pv2.x) + g*(pv3.x); - pout.y = (1.0f-f-g)*(pv1.y) + f*(pv2.y) + g*(pv3.y); - pout.z = (1.0f-f-g)*(pv1.z) + f*(pv2.z) + g*(pv3.z); - pout.w = (1.0f-f-g)*(pv1.w) + f*(pv2.w) + g*(pv3.w); - } -//+------------------------------------------------------------------+ -//| Performs a Catmull-Rom interpolation, | -//| using the specified 4D vectors. | -//+------------------------------------------------------------------+ -void DXVec4CatmullRom(DXVector4 &pout,const DXVector4 &pv0,const DXVector4 &pv1,const DXVector4 &pv2,const DXVector4 &pv3,float s) - { - pout.x = 0.5f*(2.0f*pv1.x + (pv2.x - pv0.x)*s + (2.0f*pv0.x - 5.0f*pv1.x + 4.0f*pv2.x - pv3.x)*s*s + (pv3.x -3.0f*pv2.x + 3.0f*pv1.x - pv0.x)*s*s*s); - pout.y = 0.5f*(2.0f*pv1.y + (pv2.y - pv0.y)*s + (2.0f*pv0.y - 5.0f*pv1.y + 4.0f*pv2.y - pv3.y)*s*s + (pv3.y -3.0f*pv2.y + 3.0f*pv1.y - pv0.y)*s*s*s); - pout.z = 0.5f*(2.0f*pv1.z + (pv2.z - pv0.z)*s + (2.0f*pv0.z - 5.0f*pv1.z + 4.0f*pv2.z - pv3.z)*s*s + (pv3.z -3.0f*pv2.z + 3.0f*pv1.z - pv0.z)*s*s*s); - pout.w = 0.5f*(2.0f*pv1.w + (pv2.w - pv0.w)*s + (2.0f*pv0.w - 5.0f*pv1.w + 4.0f*pv2.w - pv3.w)*s*s + (pv3.w -3.0f*pv2.w + 3.0f*pv1.w - pv0.w)*s*s*s); - } -//+------------------------------------------------------------------+ -//| Determines the cross-product in four dimensions. | -//+------------------------------------------------------------------+ -void DXVec4Cross(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2,const DXVector4 &pv3) - { - DXVector4 out; - out.x = pv1.y*(pv2.z*pv3.w - pv3.z*pv2.w) - pv1.z*(pv2.y*pv3.w - pv3.y*pv2.w) + pv1.w*(pv2.y*pv3.z - pv2.z*pv3.y); - out.y = -(pv1.x*(pv2.z*pv3.w - pv3.z*pv2.w) - pv1.z*(pv2.x*pv3.w - pv3.x*pv2.w) + pv1.w*(pv2.x*pv3.z - pv3.x*pv2.z)); - out.z = pv1.x*(pv2.y*pv3.w - pv3.y*pv2.w) - pv1.y*(pv2.x*pv3.w - pv3.x*pv2.w) + pv1.w*(pv2.x*pv3.y - pv3.x*pv2.y); - out.w = -(pv1.x*(pv2.y*pv3.z - pv3.y*pv2.z) - pv1.y*(pv2.x*pv3.z - pv3.x*pv2.z) + pv1.z*(pv2.x*pv3.y - pv3.x*pv2.y)); - pout = out; - } -//+------------------------------------------------------------------+ -//| Determines the dot product of two 4D vectors. | -//+------------------------------------------------------------------+ -float DXVec4Dot(const DXVector4 &pv1,const DXVector4 &pv2) - { - return(pv1.x*pv2.x + pv1.y*pv2.y + pv1.z*pv2.z+ pv1.w*pv2.w); - } -//+------------------------------------------------------------------+ -//| Performs a Hermite spline interpolation, | -//| using the specified 4D vectors. | -//+------------------------------------------------------------------+ -void DXVec4Hermite(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pt1,const DXVector4 &pv2,const DXVector4 &pt2,float s) - { - float h1 = 2.0f*s*s*s - 3.0f*s*s + 1.0f; - float h2 = s*s*s - 2.0f*s*s + s; - float h3 = -2.0f*s*s*s + 3.0f*s*s; - float h4 = s*s*s - s*s; - pout.x = h1*pv1.x + h2*pt1.x + h3*pv2.x + h4*pt2.x; - pout.y = h1*pv1.y + h2*pt1.y + h3*pv2.y + h4*pt2.y; - pout.z = h1*pv1.z + h2*pt1.z + h3*pv2.z + h4*pt2.z; - pout.w = h1*pv1.w + h2*pt1.w + h3*pv2.w + h4*pt2.w; - } -//+------------------------------------------------------------------+ -//| Returns the length of a 4D vector. | -//+------------------------------------------------------------------+ -float DXVec4Length(const DXVector4 &pv) - { - return((float)sqrt(pv.x*pv.x + pv.y*pv.y + pv.z*pv.z+ pv.w*pv.w)); - } -//+------------------------------------------------------------------+ -//| Returns the square of the length of a 4D vector. | -//+------------------------------------------------------------------+ -float DXVec4LengthSq(const DXVector4 &pv) - { - return((float)(pv.x*pv.x + pv.y*pv.y + pv.z*pv.z)); - } -//+------------------------------------------------------------------+ -//| Performs a linear interpolation between two 4D vectors. | -//+------------------------------------------------------------------+ -void DXVec4Lerp(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2,float s) - { - pout.x = (1.0f-s)*pv1.x + s*pv2.x; - pout.y = (1.0f-s)*pv1.y + s*pv2.y; - pout.z = (1.0f-s)*pv1.z + s*pv2.z; - pout.w = (1.0f-s)*pv1.w + s*pv2.w; - } -//+------------------------------------------------------------------+ -//| Returns a 4D vector that is made up of the largest components | -//| of two 4D vectors. | -//+------------------------------------------------------------------+ -void DXVec4Maximize(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2) - { - pout.x = (float)fmax(pv1.x,pv2.x); - pout.y = (float)fmax(pv1.y,pv2.y); - pout.z = (float)fmax(pv1.z,pv2.z); - pout.w = (float)fmax(pv1.w,pv2.w); - } -//+------------------------------------------------------------------+ -//| Returns a 4D vector that is made up of the smallest components | -//| of two 4D vectors. | -//+------------------------------------------------------------------+ -void DXVec4Minimize(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2) - { - pout.x = (float)fmin(pv1.x,pv2.x); - pout.y = (float)fmin(pv1.y,pv2.y); - pout.z = (float)fmin(pv1.z,pv2.z); - pout.w = (float)fmin(pv1.w,pv2.w); - } -//+------------------------------------------------------------------+ -//| Returns the normalized version of a 4D vector. | -//+------------------------------------------------------------------+ -void DXVec4Normalize(DXVector4 &pout,const DXVector4 &pv) - { -//--- calculate length - float norm = DXVec4Length(pv); - if(!norm) - { - pout.x = 0.0f; - pout.y = 0.0f; - pout.z = 0.0f; - pout.w = 0.0f; - } - else - { - pout.x = pv.x/norm; - pout.y = pv.y/norm; - pout.z = pv.z/norm; - pout.w = pv.w/norm; - } - } -//+------------------------------------------------------------------+ -//| Scales a 4D vector. | -//+------------------------------------------------------------------+ -void DXVec4Scale(DXVector4 &pout,const DXVector4 &pv,float s) - { - pout.x = s*pv.x; - pout.y = s*pv.y; - pout.z = s*pv.z; - pout.w = s*pv.w; - } -//+------------------------------------------------------------------+ -//| Subtracts two 4D vectors. | -//+------------------------------------------------------------------+ -void DXVec4Subtract(DXVector4 &pout,const DXVector4 &pv1,const DXVector4 &pv2) - { - pout.x = pv1.x - pv2.x; - pout.y = pv1.y - pv2.y; - pout.z = pv1.z - pv2.z; - pout.w = pv1.w - pv2.w; - } -//+------------------------------------------------------------------+ -//| Transforms a 4D vector by a given matrix. | -//+------------------------------------------------------------------+ -void DXVec4Transform(DXVector4 &pout,const DXVector4 &pv,const DXMatrix &pm) - { - DXVector4 temp; - temp.x = pm.m[0][0]*pv.x + pm.m[1][0]*pv.y + pm.m[2][0]*pv.z + pm.m[3][0]*pv.w; - temp.y = pm.m[0][1]*pv.x + pm.m[1][1]*pv.y + pm.m[2][1]*pv.z + pm.m[3][1]*pv.w; - temp.z = pm.m[0][2]*pv.x + pm.m[1][2]*pv.y + pm.m[2][2]*pv.z + pm.m[3][2]*pv.w; - temp.w = pm.m[0][3]*pv.x + pm.m[1][3]*pv.y + pm.m[2][3]*pv.z + pm.m[3][3]*pv.w; - pout=temp; - } -//+------------------------------------------------------------------+ -//| Returns a quaternion in barycentric coordinates. | -//+------------------------------------------------------------------+ -void DXQuaternionBaryCentric(DXQuaternion &pout,DXQuaternion &pq1,DXQuaternion &pq2,DXQuaternion &pq3,float f,float g) - { - DXQuaternion temp1,temp2; - DXQuaternionSlerp(temp1,pq1,pq2,f+g); - DXQuaternionSlerp(temp2,pq1,pq3,f+g); - DXQuaternionSlerp(pout,temp1,temp2,g/(f+g)); - } -//+------------------------------------------------------------------+ -//| Returns the conjugate of a quaternion. | -//+------------------------------------------------------------------+ -void DXQuaternionConjugate(DXQuaternion &pout,const DXQuaternion &pq) - { - pout.x = -pq.x; - pout.y = -pq.y; - pout.z = -pq.z; - pout.w = pq.w; - } -//+------------------------------------------------------------------+ -//| Returns the dot product of two quaternions. | -//+------------------------------------------------------------------+ -float DXQuaternionDot(DXQuaternion &a,DXQuaternion &b) - { - return(a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w); - } -//+------------------------------------------------------------------+ -//| Calculates the exponential. | -//| This method converts a pure quaternion to a unit quaternion. | -//| DXQuaternionExp expects a pure quaternion, where w is ignored | -//| in the calculation (w == 0). | -//+------------------------------------------------------------------+ -void DXQuaternionExp(DXQuaternion &out,const DXQuaternion &q) - { - float norm = (float)sqrt(q.x*q.x + q.y*q.y + q.z*q.z); - if(norm) - { - out.x = (float)sin(norm)*q.x/norm; - out.y = (float)sin(norm)*q.y/norm; - out.z = (float)sin(norm)*q.z/norm; - out.w = (float)cos(norm); - } - else - { - out.x = 0.0f; - out.y = 0.0f; - out.z = 0.0f; - out.w = 1.0f; - } - } -//+------------------------------------------------------------------+ -//| Returns the identity quaternion. | -//+------------------------------------------------------------------+ -void DXQuaternionIdentity(DXQuaternion &out) - { - out.x = 0.0f; - out.y = 0.0f; - out.z = 0.0f; - out.w = 1.0f; - } -//+------------------------------------------------------------------+ -//| Determines if a quaternion is an identity quaternion. | -//+------------------------------------------------------------------+ -bool DXQuaternionIsIdentity(DXQuaternion &pq) - { - return ((pq.x == 0.0f) && (pq.y == 0.0f) && (pq.z == 0.0f) && (pq.w == 1.0f)); - } -//+------------------------------------------------------------------+ -//| Returns the length of a quaternion. | -//+------------------------------------------------------------------+ -float DXQuaternionLength(const DXQuaternion &pq) - { - return((float)sqrt(pq.x*pq.x + pq.y*pq.y + pq.z*pq.z + pq.w*pq.w)); - } -//+------------------------------------------------------------------+ -//| Returns the square of the length of a quaternion. | -//+------------------------------------------------------------------+ -float DXQuaternionLengthSq(const DXQuaternion &pq) - { - return((float)(pq.x*pq.x + pq.y*pq.y + pq.z*pq.z + pq.w*pq.w)); - } -//+------------------------------------------------------------------+ -//| Conjugates and renormalizes a quaternion. | -//+------------------------------------------------------------------+ -void DXQuaternionInverse(DXQuaternion &pout,const DXQuaternion &pq) - { - float norm = DXQuaternionLengthSq(pq); - pout.x = -pq.x/norm; - pout.y = -pq.y/norm; - pout.z = -pq.z/norm; - pout.w = pq.w/norm; - } -//+------------------------------------------------------------------+ -//| Calculates the natural logarithm. | -//| The DXQuaternionLn function works only for unit quaternions. | -//+------------------------------------------------------------------+ -void DXQuaternionLn(DXQuaternion &out,const DXQuaternion &q) - { - float t; - if((q.w >= 1.0f) || (q.w == -1.0f)) - t = 1.0f; - else - t = (float)(acos(q.w)/sqrt(1.0f - q.w*q.w)); - out.x = t*q.x; - out.y = t*q.y; - out.z = t*q.z; - out.w = 0.0f; - } -//+------------------------------------------------------------------+ -//| Multiplies two quaternions. | -//+------------------------------------------------------------------+ -void DXQuaternionMultiply(DXQuaternion &pout,const DXQuaternion &pq1,const DXQuaternion &pq2) - { - DXQuaternion out; - out.x = pq2.w*pq1.x + pq2.x*pq1.w + pq2.y*pq1.z - pq2.z*pq1.y; - out.y = pq2.w*pq1.y - pq2.x*pq1.z + pq2.y*pq1.w + pq2.z*pq1.x; - out.z = pq2.w*pq1.z + pq2.x*pq1.y - pq2.y*pq1.x + pq2.z*pq1.w; - out.w = pq2.w*pq1.w - pq2.x*pq1.x - pq2.y*pq1.y - pq2.z*pq1.z; - pout = out; - } -//+------------------------------------------------------------------+ -//| Computes a unit length quaternion. | -//+------------------------------------------------------------------+ -void DXQuaternionNormalize(DXQuaternion &out,const DXQuaternion &q) - { - float norm = DXQuaternionLength(q); - if(!norm) - { - out.x = 0.0f; - out.y = 0.0f; - out.z = 0.0f; - out.w = 0.0f; - } - else - { - out.x = q.x/norm; - out.y = q.y/norm; - out.z = q.z/norm; - out.w = q.w/norm; - } - } -//+------------------------------------------------------------------+ -//| Rotates a quaternion about an arbitrary axis. | -//+------------------------------------------------------------------+ -void DXQuaternionRotationAxis(DXQuaternion &out,const DXVector3 &v,float angle) - { - DXVector3 temp; - DXVec3Normalize(temp,v); - out.x = (float)sin(angle/2.0f)*temp.x; - out.y = (float)sin(angle/2.0f)*temp.y; - out.z = (float)sin(angle/2.0f)*temp.z; - out.w = (float)cos(angle/2.0f); - } -//+------------------------------------------------------------------+ -//| Builds a quaternion from a rotation matrix. | -//+------------------------------------------------------------------+ -void DXQuaternionRotationMatrix(DXQuaternion &out,const DXMatrix &m) - { - float s; - float trace = m.m[0][0] + m.m[1][1] + m.m[2][2] + 1.0f; - if(trace>1.0f) - { - s = 2.0f*(float)sqrt(trace); - out.x = (m.m[1][2] - m.m[2][1])/s; - out.y = (m.m[2][0] - m.m[0][2])/s; - out.z = (m.m[0][1] - m.m[1][0])/s; - out.w = 0.25f*s; - } - else - { - int maxi = 0; - for(int i=1; i<3; i++) - { - if(m.m[i][i] > m.m[maxi][maxi]) - maxi = i; - } - switch(maxi) - { - case 0: - s = 2.0f*(float)sqrt(1.0f + m.m[0][0] - m.m[1][1] - m.m[2][2]); - out.x = 0.25f*s; - out.y = (m.m[0][1] + m.m[1][0])/s; - out.z = (m.m[0][2] + m.m[2][0])/s; - out.w = (m.m[1][2] - m.m[2][1])/s; - break; - - case 1: - s = 2.0f*(float)sqrt(1.0f + m.m[1][1] - m.m[0][0] - m.m[2][2]); - out.x = (m.m[0][1] + m.m[1][0])/s; - out.y = 0.25f*s; - out.z = (m.m[1][2] + m.m[2][1])/s; - out.w = (m.m[2][0] - m.m[0][2])/s; - break; - - case 2: - s = 2.0f*(float)sqrt(1.0f + m.m[2][2] - m.m[0][0] - m.m[1][1]); - out.x = (m.m[0][2] + m.m[2][0])/s; - out.y = (m.m[1][2] + m.m[2][1])/s; - out.z = 0.25f*s; - out.w = (m.m[0][1] - m.m[1][0])/s; - break; - } - } - } -//+------------------------------------------------------------------+ -//| Builds a quaternion with the given yaw, pitch, and roll. | -//+------------------------------------------------------------------+ -void DXQuaternionRotationYawPitchRoll(DXQuaternion &out,float yaw,float pitch,float roll) - { - float syaw = (float)sin(yaw/2.0f); - float cyaw = (float)cos(yaw/2.0f); - float spitch = (float)sin(pitch/2.0f); - float cpitch = (float)cos(pitch/2.0f); - float sroll = (float)sin(roll/2.0f); - float croll = (float)cos(roll/2.0f); -//--- - out.x = syaw*cpitch*sroll + cyaw*spitch*croll; - out.y = syaw*cpitch*croll - cyaw*spitch*sroll; - out.z = cyaw*cpitch*sroll - syaw*spitch*croll; - out.w = cyaw*cpitch*croll + syaw*spitch*sroll; - } -//+------------------------------------------------------------------+ -//| Interpolates between two quaternions, using spherical linear | -//| interpolation. | -//+------------------------------------------------------------------+ -void DXQuaternionSlerp(DXQuaternion &out,DXQuaternion &q1,DXQuaternion &q2,float t) - { - float temp = 1.0f - t; - float dot = DXQuaternionDot(q1,q2); - if(dot<0.0f) - { - t = -t; - dot = -dot; - } - if(1.0f-dot>0.001f) - { - float theta = (float)acos(dot); - temp = (float)sin(theta*temp)/(float)sin(theta); - t = (float)sin(theta*t)/(float)sin(theta); - } - out.x = temp*q1.x + t*q2.x; - out.y = temp*q1.y + t*q2.y; - out.z = temp*q1.z + t*q2.z; - out.w = temp*q1.w + t*q2.w; - } -//+------------------------------------------------------------------+ -//| Interpolates between quaternions, using spherical quadrangle | -//| interpolation. | -//+------------------------------------------------------------------+ -void DXQuaternionSquad(DXQuaternion &pout,DXQuaternion &pq1,DXQuaternion &pq2,DXQuaternion &pq3,DXQuaternion &pq4,float t) - { - DXQuaternion temp1,temp2; - DXQuaternionSlerp(temp1,pq1,pq4,t); - DXQuaternionSlerp(temp2,pq2,pq3,t); - DXQuaternionSlerp(pout,temp1,temp2,2.0f*t*(1.0f - t)); - } -//+------------------------------------------------------------------+ -//| add_diff | -//+------------------------------------------------------------------+ -DXQuaternion add_diff(const DXQuaternion &q1,const DXQuaternion &q2,const float add) - { - DXQuaternion temp; - temp.x = q1.x + add * q2.x; - temp.y = q1.y + add * q2.y; - temp.z = q1.z + add * q2.z; - temp.w = q1.w + add * q2.w; -//--- - return(temp); - } -//+------------------------------------------------------------------+ -//| Sets up control points for spherical quadrangle interpolation. | -//+------------------------------------------------------------------+ -void DXQuaternionSquadSetup(DXQuaternion &paout,DXQuaternion &pbout,DXQuaternion &pcout,DXQuaternion &pq0,DXQuaternion &pq1,DXQuaternion &pq2,DXQuaternion &pq3) - { - DXQuaternion q,temp1,temp2,temp3,zero; - DXQuaternion aout,cout; - zero.x = 0.0f; - zero.y = 0.0f; - zero.z = 0.0f; - zero.w = 0.0f; -//--- - if(DXQuaternionDot(pq0,pq1) < 0.0f) - temp2 = add_diff(zero,pq0,-1.0f); - else - temp2 = pq0; -//--- - if(DXQuaternionDot(pq1,pq2) < 0.0f) - cout = add_diff(zero,pq2,-1.0f); - else - cout = pq2; -//--- - if(DXQuaternionDot(cout,pq3) < 0.0f) - temp3 = add_diff(zero,pq3,-1.0f); - else - temp3 = pq3; -//--- - DXQuaternionInverse(temp1,pq1); - DXQuaternionMultiply(temp2,temp1,temp2); - DXQuaternionLn(temp2,temp2); - DXQuaternionMultiply(q,temp1,cout); - DXQuaternionLn(q,q); - temp1 = add_diff(temp2,q,1.0f); - temp1.x *= -0.25f; - temp1.y *= -0.25f; - temp1.z *= -0.25f; - temp1.w *= -0.25f; - DXQuaternionExp(temp1,temp1); - DXQuaternionMultiply(aout,pq1,temp1); -//--- - DXQuaternionInverse(temp1,cout); - DXQuaternionMultiply(temp2,temp1,pq1); - DXQuaternionLn(temp2,temp2); - DXQuaternionMultiply(q,temp1,temp3); - DXQuaternionLn(q,q); - temp1 = add_diff(temp2,q,1.0f); - temp1.x *= -0.25f; - temp1.y *= -0.25f; - temp1.z *= -0.25f; - temp1.w *= -0.25f; - DXQuaternionExp(temp1,temp1); - DXQuaternionMultiply(pbout,cout,temp1); - paout = aout; - pcout = cout; - } -//+------------------------------------------------------------------+ -//| Computes a quaternion's axis and angle of rotation. | -//+------------------------------------------------------------------+ -void DXQuaternionToAxisAngle(const DXQuaternion &pq,DXVector3 &paxis,float &pangle) - { -//--- paxis - paxis.x = pq.x; - paxis.y = pq.y; - paxis.z = pq.z; -//--- pangle - pangle = 2.0f*(float)acos(pq.w); - } -//+------------------------------------------------------------------+ -//| DXMatrixIdentity creates an identity matrix | -//+------------------------------------------------------------------+ -void DXMatrixIdentity(DXMatrix &out) - { - for(int j=0; j<4; j++) - for(int i=0; i<4; i++) - { - if(i==j) - out.m[j,i]=1.0f; - else - out.m[j,i]=0.0f; - } - } -//+------------------------------------------------------------------+ -//| Determines if a matrix is an identity matrix. | -//+------------------------------------------------------------------+ -bool DXMatrixIsIdentity(DXMatrix &pm) - { - for(int j=0; j<4; j++) - for(int i=0; i<4; i++) - { - if(i==j) - { - if(fabs(pm.m[j,i]-1.0f)>1e-6f) - return(false); - } - else - if(fabs(pm.m[j,i])>1e-6f) - return(false); - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Builds a 3D affine transformation matrix. | -//+------------------------------------------------------------------+ -//| This function calculates the affine transformation matrix | -//| with the following formula, with matrix concatenation | -//| evaluated in left-to-right order: | -//| Mout = Ms * (Mrc)-1 * Mr * Mrc * Mt | -//| where: | -//| Mout = output matrix (pOut) | -//| Ms = scaling matrix (Scaling) | -//| Mrc = center of rotation matrix (pRotationCenter) | -//| Mr = rotation matrix (pRotation) | -//| Mt = translation matrix (pTranslation) | -//+------------------------------------------------------------------+ -void DXMatrixAffineTransformation(DXMatrix &out,float scaling,const DXVector3 &rotationcenter,const DXQuaternion &rotation,const DXVector3 &translation) - { - DXMatrixIdentity(out); -//--- rotation - float temp00 = 1.0f - 2.0f*(rotation.y*rotation.y + rotation.z*rotation.z); - float temp01 = 2.0f * (rotation.x*rotation.y + rotation.z*rotation.w); - float temp02 = 2.0f * (rotation.x*rotation.z - rotation.y*rotation.w); - float temp10 = 2.0f * (rotation.x*rotation.y - rotation.z*rotation.w); - float temp11 = 1.0f - 2.0f*(rotation.x*rotation.x + rotation.z*rotation.z); - float temp12 = 2.0f * (rotation.y*rotation.z + rotation.x*rotation.w); - float temp20 = 2.0f * (rotation.x*rotation.z + rotation.y*rotation.w); - float temp21 = 2.0f * (rotation.y*rotation.z - rotation.x*rotation.w); - float temp22 = 1.0f - 2.0f*(rotation.x*rotation.x + rotation.y*rotation.y); -//--- scaling - out.m[0][0] = scaling*temp00; - out.m[0][1] = scaling*temp01; - out.m[0][2] = scaling*temp02; - out.m[1][0] = scaling*temp10; - out.m[1][1] = scaling*temp11; - out.m[1][2] = scaling*temp12; - out.m[2][0] = scaling*temp20; - out.m[2][1] = scaling*temp21; - out.m[2][2] = scaling*temp22; -//--- rotationcenter - out.m[3][0] = rotationcenter.x*(1.0f - temp00) - rotationcenter.y*temp10 - rotationcenter.z*temp20; - out.m[3][1] = rotationcenter.y*(1.0f - temp11) - rotationcenter.x*temp01 - rotationcenter.z*temp21; - out.m[3][2] = rotationcenter.z*(1.0f - temp22) - rotationcenter.x*temp02 - rotationcenter.y*temp12; -//--- translation - out.m[3][0] += translation.x; - out.m[3][1] += translation.y; - out.m[3][2] += translation.z; - } -//+------------------------------------------------------------------+ -//| Builds a 2D affine transformation matrix in the xy plane. | -//+------------------------------------------------------------------+ -//| This function calculates the affine transformation matrix | -//| with the following formula, with matrix concatenation evaluated | -//| in left-to-right order: | -//| Mout = Ms * (Mrc)^(-1) * Mr * Mrc * Mt | -//| where: | -//| Mout = output matrix (pOut) | -//| Ms = scaling matrix (Scaling) | -//| Mrc = center of rotation matrix (pRotationCenter) | -//| Mr = rotation matrix (Rotation) | -//| Mt = translation matrix (pTranslation) | -//+------------------------------------------------------------------+ -void DXMatrixAffineTransformation2D(DXMatrix &out,float scaling,const DXVector2 &rotationcenter,float rotation,const DXVector2 &translation) - { - float s = (float)sin(rotation/2.0f); - float tmp1 = 1.0f - 2.0f*s*s; - float tmp2 = 2.0f*s*(float)cos(rotation/2.0f); -//--- - DXMatrixIdentity(out); - out.m[0][0] = scaling*tmp1; - out.m[0][1] = scaling*tmp2; - out.m[1][0] = -scaling*tmp2; - out.m[1][1] = scaling*tmp1; -//--- rotationcenter - float x = rotationcenter.x; - float y = rotationcenter.y; - out.m[3][0] = y*tmp2 - x*tmp1 + x; - out.m[3][1] = -x*tmp2 - y*tmp1 + y; -//--- translation - out.m[3][0] += translation.x; - out.m[3][1] += translation.y; - } -#define D3DERR_INVALIDCALL -2005530516 -//#define S_OK 0; -//+------------------------------------------------------------------+ -//| Breaks down a general 3D transformation matrix into its scalar, | -//| rotational, and translational components. | -//+------------------------------------------------------------------+ -int DXMatrixDecompose(DXVector3 &poutscale,DXQuaternion &poutrotation,DXVector3 &pouttranslation,const DXMatrix &pm) - { - DXMatrix normalized; - DXVector3 vec; -//--- Compute the scaling part - vec.x=pm.m[0][0]; - vec.y=pm.m[0][1]; - vec.z=pm.m[0][2]; - poutscale.x=DXVec3Length(vec); - vec.x=pm.m[1][0]; - vec.y=pm.m[1][1]; - vec.z=pm.m[1][2]; - poutscale.y=DXVec3Length(vec); - vec.x=pm.m[2][0]; - vec.y=pm.m[2][1]; - vec.z=pm.m[2][2]; - poutscale.z=DXVec3Length(vec); -//--- compute the translation part - pouttranslation.x=pm.m[3][0]; - pouttranslation.y=pm.m[3][1]; - pouttranslation.z=pm.m[3][2]; -//--- let's calculate the rotation now - if((poutscale.x == 0.0f) || (poutscale.y == 0.0f) || (poutscale.z == 0.0f)) - return(D3DERR_INVALIDCALL); -//--- - normalized.m[0][0]=pm.m[0][0]/poutscale.x; - normalized.m[0][1]=pm.m[0][1]/poutscale.x; - normalized.m[0][2]=pm.m[0][2]/poutscale.x; - normalized.m[1][0]=pm.m[1][0]/poutscale.y; - normalized.m[1][1]=pm.m[1][1]/poutscale.y; - normalized.m[1][2]=pm.m[1][2]/poutscale.y; - normalized.m[2][0]=pm.m[2][0]/poutscale.z; - normalized.m[2][1]=pm.m[2][1]/poutscale.z; - normalized.m[2][2]=pm.m[2][2]/poutscale.z; - DXQuaternionRotationMatrix(poutrotation,normalized); -//--- - return(0); - } -//+------------------------------------------------------------------+ -//| Returns the determinant of a matrix. | -//+------------------------------------------------------------------+ -float DXMatrixDeterminant(const DXMatrix &pm) - { - float t[3],v[4]; - t[0] = pm.m[2][2]*pm.m[3][3] - pm.m[2][3]*pm.m[3][2]; - t[1] = pm.m[1][2]*pm.m[3][3] - pm.m[1][3]*pm.m[3][2]; - t[2] = pm.m[1][2]*pm.m[2][3] - pm.m[1][3]*pm.m[2][2]; - v[0] = pm.m[1][1]*t[0] - pm.m[2][1] * t[1] + pm.m[3][1]*t[2]; - v[1] = -pm.m[1][0]*t[0] + pm.m[2][0] * t[1] - pm.m[3][0]*t[2]; -//--- - t[0] = pm.m[1][0]*pm.m[2][1] - pm.m[2][0]*pm.m[1][1]; - t[1] = pm.m[1][0]*pm.m[3][1] - pm.m[3][0]*pm.m[1][1]; - t[2] = pm.m[2][0]*pm.m[3][1] - pm.m[3][0]*pm.m[2][1]; - v[2] = pm.m[3][3]*t[0] - pm.m[2][3]*t[1] + pm.m[1][3]*t[2]; - v[3] = -pm.m[3][2]*t[0] + pm.m[2][2]*t[1] - pm.m[1][2]*t[2]; -//--- - return(pm.m[0][0]*v[0] + pm.m[0][1]*v[1] + pm.m[0][2]*v[2] + pm.m[0][3]*v[3]); - } -//+------------------------------------------------------------------+ -//| Calculates the inverse of a matrix. | -//+------------------------------------------------------------------+ -void DXMatrixInverse(DXMatrix &pout,float &pdeterminant,const DXMatrix &pm) - { - float t[3],v[16]; - t[0] = pm.m[2][2]*pm.m[3][3] - pm.m[2][3]*pm.m[3][2]; - t[1] = pm.m[1][2]*pm.m[3][3] - pm.m[1][3]*pm.m[3][2]; - t[2] = pm.m[1][2]*pm.m[2][3] - pm.m[1][3]*pm.m[2][2]; - v[0] = pm.m[1][1]*t[0] - pm.m[2][1]*t[1] + pm.m[3][1]*t[2]; - v[4] = -pm.m[1][0]*t[0] + pm.m[2][0]*t[1] - pm.m[3][0]*t[2]; -//--- - t[0] = pm.m[1][0]*pm.m[2][1] - pm.m[2][0]*pm.m[1][1]; - t[1] = pm.m[1][0]*pm.m[3][1] - pm.m[3][0]*pm.m[1][1]; - t[2] = pm.m[2][0]*pm.m[3][1] - pm.m[3][0]*pm.m[2][1]; - v[8] = pm.m[3][3]*t[0] - pm.m[2][3]*t[1] + pm.m[1][3]*t[2]; - v[12] = -pm.m[3][2]*t[0] + pm.m[2][2]*t[1] - pm.m[1][2]*t[2]; -//--- - float det = pm.m[0][0]*v[0] + pm.m[0][1]*v[4] + pm.m[0][2]*v[8] + pm.m[0][3]*v[12]; - if(det == 0.0f) - { - for(int j=0; j<4; j++) - for(int i=0; i<4; i++) - { - pout.m[j,i]=0.0; - } - //--- - return; - } - if(pdeterminant) - pdeterminant = det; -//--- - t[0] = pm.m[2][2]*pm.m[3][3] - pm.m[2][3]*pm.m[3][2]; - t[1] = pm.m[0][2]*pm.m[3][3] - pm.m[0][3]*pm.m[3][2]; - t[2] = pm.m[0][2]*pm.m[2][3] - pm.m[0][3]*pm.m[2][2]; - v[1] = -pm.m[0][1]*t[0] + pm.m[2][1]*t[1] - pm.m[3][1]*t[2]; - v[5] = pm.m[0][0]*t[0] - pm.m[2][0]*t[1] + pm.m[3][0]*t[2]; -//--- - t[0] = pm.m[0][0]*pm.m[2][1] - pm.m[2][0] * pm.m[0][1]; - t[1] = pm.m[3][0]*pm.m[0][1] - pm.m[0][0] * pm.m[3][1]; - t[2] = pm.m[2][0]*pm.m[3][1] - pm.m[3][0] * pm.m[2][1]; - v[9] = -pm.m[3][3]*t[0] - pm.m[2][3]*t[1]- pm.m[0][3]*t[2]; - v[13] = pm.m[3][2]*t[0] + pm.m[2][2]*t[1] + pm.m[0][2]*t[2]; -//--- - t[0] = pm.m[1][2]*pm.m[3][3] - pm.m[1][3] * pm.m[3][2]; - t[1] = pm.m[0][2]*pm.m[3][3] - pm.m[0][3] * pm.m[3][2]; - t[2] = pm.m[0][2]*pm.m[1][3] - pm.m[0][3] * pm.m[1][2]; - v[2] = pm.m[0][1]*t[0] - pm.m[1][1]*t[1] + pm.m[3][1]*t[2]; - v[6] = -pm.m[0][0]*t[0] + pm.m[1][0]*t[1] - pm.m[3][0]*t[2]; -//--- - t[0] = pm.m[0][0]*pm.m[1][1] - pm.m[1][0] * pm.m[0][1]; - t[1] = pm.m[3][0]*pm.m[0][1] - pm.m[0][0] * pm.m[3][1]; - t[2] = pm.m[1][0]*pm.m[3][1] - pm.m[3][0] * pm.m[1][1]; - v[10] = pm.m[3][3]*t[0] + pm.m[1][3]*t[1] + pm.m[0][3]*t[2]; - v[14] = -pm.m[3][2]*t[0] - pm.m[1][2]*t[1] - pm.m[0][2]*t[2]; -//--- - t[0] = pm.m[1][2]*pm.m[2][3] - pm.m[1][3] * pm.m[2][2]; - t[1] = pm.m[0][2]*pm.m[2][3] - pm.m[0][3] * pm.m[2][2]; - t[2] = pm.m[0][2]*pm.m[1][3] - pm.m[0][3] * pm.m[1][2]; - v[3] = -pm.m[0][1]*t[0] + pm.m[1][1]*t[1] - pm.m[2][1]*t[2]; - v[7] = pm.m[0][0]*t[0] - pm.m[1][0]*t[1] + pm.m[2][0]*t[2]; -//--- - v[11] = -pm.m[0][0]*(pm.m[1][1]*pm.m[2][3] - pm.m[1][3]*pm.m[2][1]) + - pm.m[1][0]*(pm.m[0][1]*pm.m[2][3] - pm.m[0][3]*pm.m[2][1]) - - pm.m[2][0]*(pm.m[0][1]*pm.m[1][3] - pm.m[0][3]*pm.m[1][1]); -//--- - v[15] = pm.m[0][0]*(pm.m[1][1]*pm.m[2][2] - pm.m[1][2]*pm.m[2][1]) - - pm.m[1][0]*(pm.m[0][1]*pm.m[2][2] - pm.m[0][2]*pm.m[2][1]) + - pm.m[2][0]*(pm.m[0][1]*pm.m[1][2] - pm.m[0][2]*pm.m[1][1]); -//--- - det = 1.0f/det; - for(int i=0; i<4; i++) - for(int j=0; j<4; j++) - pout.m[i][j] = v[4*i + j]*det; - } -//+------------------------------------------------------------------+ -//| Builds a left-handed,look-at matrix. | -//| This function uses the following formula to compute | -//| the returned matrix. | -//| | -//| zaxis = normal(At - Eye) | -//| xaxis = normal(cross(Up,zaxis)) | -//| yaxis = cross(zaxis,xaxis) | -//| | -//| xaxis.x yaxis.x zaxis.x 0 | -//| xaxis.y yaxis.y zaxis.y 0 | -//| xaxis.z yaxis.z zaxis.z 0 | -//| -dot(xaxis,eye) -dot(yaxis,eye) -dot(zaxis,eye) 1 | -//+------------------------------------------------------------------+ -void DXMatrixLookAtLH(DXMatrix &out,const DXVector3 &eye,const DXVector3 &at,const DXVector3 &up) - { - DXVector3 right,upn,vec; - DXVec3Subtract(vec,at,eye); - DXVec3Normalize(vec,vec); - DXVec3Cross(right,up,vec); - DXVec3Cross(upn,vec,right); - DXVec3Normalize(right,right); - DXVec3Normalize(upn,upn); -//--- - out.m[0][0] = right.x; - out.m[1][0] = right.y; - out.m[2][0] = right.z; - out.m[3][0] = -DXVec3Dot(right,eye); - out.m[0][1] = upn.x; - out.m[1][1] = upn.y; - out.m[2][1] = upn.z; - out.m[3][1] = -DXVec3Dot(upn,eye); - out.m[0][2] = vec.x; - out.m[1][2] = vec.y; - out.m[2][2] = vec.z; - out.m[3][2] = -DXVec3Dot(vec,eye); - out.m[0][3] = 0.0f; - out.m[1][3] = 0.0f; - out.m[2][3] = 0.0f; - out.m[3][3] = 1.0f; - } -//+------------------------------------------------------------------+ -//| Builds a right-handed, look-at matrix. | -//+------------------------------------------------------------------+ -//| This function uses the following formula to compute | -//| the returned matrix. | -//| | -//| zaxis = normal(Eye - At) | -//| xaxis = normal(cross(Up,zaxis)) | -//| yaxis = cross(zaxis,xaxis) | -//| | -//| xaxis.x yaxis.x zaxis.x 0 | -//| xaxis.y yaxis.y zaxis.y 0 | -//| xaxis.z yaxis.z zaxis.z 0 | -//| dot(xaxis,eye) dot(yaxis,eye) dot(zaxis,eye) 1 | -//+------------------------------------------------------------------+ -void DXMatrixLookAtRH(DXMatrix &out,const DXVector3 &eye,const DXVector3 &at,const DXVector3 &up) - { - DXVector3 right,upn,vec; - DXVec3Subtract(vec,at,eye); - DXVec3Normalize(vec,vec); - DXVec3Cross(right,up,vec); - DXVec3Cross(upn,vec,right); - DXVec3Normalize(right,right); - DXVec3Normalize(upn,upn); -//--- - out.m[0][0] = -right.x; - out.m[1][0] = -right.y; - out.m[2][0] = -right.z; - out.m[3][0] = DXVec3Dot(right,eye); - out.m[0][1] = upn.x; - out.m[1][1] = upn.y; - out.m[2][1] = upn.z; - out.m[3][1] = -DXVec3Dot(upn,eye); - out.m[0][2] = -vec.x; - out.m[1][2] = -vec.y; - out.m[2][2] = -vec.z; - out.m[3][2] = DXVec3Dot(vec,eye); - out.m[0][3] = 0.0f; - out.m[1][3] = 0.0f; - out.m[2][3] = 0.0f; - out.m[3][3] = 1.0f; - } -//+------------------------------------------------------------------+ -//| Determines the product of two matrices. | -//+------------------------------------------------------------------+ -void DXMatrixMultiply(DXMatrix &pout,const DXMatrix &pm1,const DXMatrix &pm2) - { - DXMatrix out= {}; - for(int i=0; i<4; i++) - { - for(int j=0; j<4; j++) - { - out.m[i][j] = pm1.m[i][0]*pm2.m[0][j] + pm1.m[i][1]*pm2.m[1][j] + pm1.m[i][2]*pm2.m[2][j] + pm1.m[i][3]*pm2.m[3][j]; - } - } - pout = out; - } -//+------------------------------------------------------------------+ -//| Calculates the transposed product of two matrices. | -//+------------------------------------------------------------------+ -void DXMatrixMultiplyTranspose(DXMatrix &pout,const DXMatrix &pm1,const DXMatrix &pm2) - { - DXMatrix temp= {}; - for(int i = 0; i < 4; i++) - for(int j = 0; j < 4; j++) - temp.m[j][i] = pm1.m[i][0]*pm2.m[0][j] + pm1.m[i][1]*pm2.m[1][j] + pm1.m[i][2]*pm2.m[2][j] + pm1.m[i][3]*pm2.m[3][j]; - pout = temp; - } -//+------------------------------------------------------------------+ -//| Builds a left-handed orthographic projection matrix. | -//+------------------------------------------------------------------+ -void DXMatrixOrthoLH(DXMatrix &pout,float w,float h,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f/w; - pout.m[1][1] = 2.0f/h; - pout.m[2][2] = 1.0f/(zf - zn); - pout.m[3][2] = zn/(zn - zf); - } -//+------------------------------------------------------------------+ -//| Builds a customized,left-handed orthographic projection matrix. | -//+------------------------------------------------------------------+ -void DXMatrixOrthoOffCenterLH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f/(r - l); - pout.m[1][1] = 2.0f/(t - b); - pout.m[2][2] = 1.0f/(zf -zn); - pout.m[3][0] = -1.0f -2.0f*l/(r - l); - pout.m[3][1] = 1.0f + 2.0f*t/(b - t); - pout.m[3][2] = zn/(zn -zf); - } -//+------------------------------------------------------------------+ -//| Builds a customized,right-handed orthographic projection matrix. | -//+------------------------------------------------------------------+ -void DXMatrixOrthoOffCenterRH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f/(r - l); - pout.m[1][1] = 2.0f/(t - b); - pout.m[2][2] = 1.0f/(zn -zf); - pout.m[3][0] = -1.0f -2.0f*l/(r - l); - pout.m[3][1] = 1.0f + 2.0f*t/(b - t); - pout.m[3][2] = zn/(zn -zf); - } -//+------------------------------------------------------------------+ -//| Builds a right-handed orthographic projection matrix. | -//+------------------------------------------------------------------+ -//| All the parameters of the DXMatrixOrthoRH function | -//| are distances in camera space. The parameters describe | -//| the dimensions of the view volume. | -//| | -//| This function uses the following formula to compute | -//| the returned matrix: | -//| 2/w 0 0 0 | -//| 0 2/h 0 0 | -//| 0 0 1/(zn-zf) 0 | -//| 0 0 zn/(zn-zf) 1 | -//+------------------------------------------------------------------+ -void DXMatrixOrthoRH(DXMatrix &pout,float w,float h,float zn,float zf) - { - DXMatrixIdentity(pout); - pout.m[0][0] = 2.0f/w; - pout.m[1][1] = 2.0f/h; - pout.m[2][2] = 1.0f/(zn - zf); - pout.m[3][2] = zn/(zn - zf); - } -//+------------------------------------------------------------------+ -//| Builds a left-handed perspective projection matrix | -//| based on a field of view. | -//+------------------------------------------------------------------+ -//| This function computes the returned matrix as shown: | -//| xScale 0 0 0 | -//| 0 yScale 0 0 | -//| 0 0 zf/(zf-zn) 1 | -//| 0 0 -zn*zf/(zf-zn) 0 | -//| where: | -//| yScale = cot(fovY/2) | -//| xScale = yScale / aspect ratio | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveFovLH(DXMatrix &pout,float fovy,float aspect,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 1.0f/(aspect*(float)tan(fovy/2.0f)); - pout.m[1][1] = 1.0f/(float)tan(fovy/2.0f); - pout.m[2][2] = zf/(zf - zn); - pout.m[2][3] = 1.0f; - pout.m[3][2] = (zf*zn)/(zn - zf); - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a right-handed perspective projection matrix | -//| based on a field of view. | -//+------------------------------------------------------------------+ -//| This function computes the returned matrix as shown. | -//| xScale 0 0 0 | -//| 0 yScale 0 0 | -//| 0 0 zf/(zn-zf) -1 | -//| 0 0 zn*zf/(zn-zf) 0 | -//| where: | -//| yScale = cot(fovY/2) | -//| xScale = yScale / aspect ratio | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveFovRH(DXMatrix &pout,float fovy,float aspect,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 1.0f/(aspect*(float)tan(fovy/2.0f)); - pout.m[1][1] = 1.0f/(float)tan(fovy/2.0f); - pout.m[2][2] = zf/(zn - zf); - pout.m[2][3] = -1.0f; - pout.m[3][2] = (zf*zn)/(zn - zf); - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a left-handed perspective projection matrix | -//+------------------------------------------------------------------+ -//| This function uses the following formula to compute | -//| the returned matrix. | -//| 2*zn/w 0 0 0 | -//| 0 2*zn/h 0 0 | -//| 0 0 zf/(zf-zn) 1 | -//| 0 0 zn*zf/(zn-zf) 0 | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveLH(DXMatrix &pout,float w,float h,float zn,float zf) - { - DXMatrixIdentity(pout); - pout.m[0][0] = 2.0f*zn/w; - pout.m[1][1] = 2.0f*zn/h; - pout.m[2][2] = zf/(zf - zn); - pout.m[3][2] = (zn*zf)/(zn - zf); - pout.m[2][3] = 1.0f; - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a customized, left-handed perspective projection matrix. | -//+------------------------------------------------------------------+ -//| All the parameters of the DXMatrixPerspectiveOffCenterLH | -//| function are distances in camera space. The parameters describe | -//| the dimensions of the view volume. | -//| | -//| This function uses the following formula to compute | -//| the returned matrix. | -//| 2*zn/(r-l) 0 0 0 | -//| 0 2*zn/(t-b) 0 0 | -//| (l+r)/(l-r) (t+b)/(b-t) zf/(zf-zn) 1 | -//| 0 0 zn*zf/(zn-zf) 0 | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveOffCenterLH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f*zn/(r - l); - pout.m[1][1] = -2.0f*zn/(b - t); - pout.m[2][0] = -1.0f - 2.0f*l/(r - l); - pout.m[2][1] = 1.0f + 2.0f*t/(b - t); - pout.m[2][2] = - zf/(zn - zf); - pout.m[3][2] = (zn*zf)/(zn -zf); - pout.m[2][3] = 1.0f; - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a customized, right-handed perspective projection matrix. | -//+------------------------------------------------------------------+ -//| All the parameters of the DXMatrixPerspectiveOffCenterRH | -//| function are distances in camera space. The parameters describe | -//| the dimensions of the view volume. | -//| | -//| This function uses the following formula to compute | -//| the returned matrix. | -//| 2*zn/(r-l) 0 0 0 | -//| 0 2*zn/(t-b) 0 0 | -//| (l+r)/(r-l) (t+b)/(t-b) zf/(zn-zf) -1 | -//| 0 0 zn*zf/(zn-zf) 0 | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveOffCenterRH(DXMatrix &pout,float l,float r,float b,float t,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f*zn/(r - l); - pout.m[1][1] = -2.0f*zn/(b - t); - pout.m[2][0] = 1.0f + 2.0f*l/(r - l); - pout.m[2][1] = -1.0f -2.0f*t/(b - t); - pout.m[2][2] = zf/(zn - zf); - pout.m[3][2] = (zn*zf)/(zn -zf); - pout.m[2][3] = -1.0f; - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a right-handed perspective projection matrix. | -//+------------------------------------------------------------------+ -//| All the parameters of the DXMatrixPerspectiveRH function | -//| are distances in camera space. The parameters describe | -//| the dimensions of the view volume. | -//| | -//| This function uses the following formula to compute | -//| the returned matrix. | -//| 2*zn/w 0 0 0 | -//| 0 2*zn/h 0 0 | -//| 0 0 zf/(zn-zf) -1 | -//| 0 0 zn*zf/(zn-zf) 0 | -//+------------------------------------------------------------------+ -void DXMatrixPerspectiveRH(DXMatrix &pout,float w,float h,float zn,float zf) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 2.0f*zn/w; - pout.m[1][1] = 2.0f*zn/h; - pout.m[2][2] = zf/(zn - zf); - pout.m[3][2] = (zn*zf)/(zn - zf); - pout.m[2][3] = -1.0f; - pout.m[3][3] = 0.0f; - } -//+------------------------------------------------------------------+ -//| Builds a matrix that reflects the coordinate system about a plane| -//| This function normalizes the plane equation before it creates | -//| the reflected matrix. | -//| | -//| This function uses the following formula to compute | -//| the returned matrix. | -//| P = normalize(Plane); | -//| -2 * P.a * P.a + 1 -2 * P.b * P.a -2 * P.c * P.a 0 | -//| -2 * P.a * P.b -2 * P.b * P.b + 1 -2 * P.c * P.b 0 | -//| -2 * P.a * P.c -2 * P.b * P.c -2 * P.c * P.c + 1 0 | -//| -2 * P.a * P.d -2 * P.b * P.d -2 * P.c * P.d 1 | -//+------------------------------------------------------------------+ -void DXMatrixReflect(DXMatrix &pout,const DXPlane &pplane) - { - DXPlane Nplane; - DXPlaneNormalize(Nplane,pplane); - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 1.0f - 2.0f*Nplane.a*Nplane.a; - pout.m[0][1] = -2.0f*Nplane.a*Nplane.b; - pout.m[0][2] = -2.0f*Nplane.a*Nplane.c; - pout.m[1][0] = -2.0f*Nplane.a*Nplane.b; - pout.m[1][1] = 1.0f - 2.0f*Nplane.b*Nplane.b; - pout.m[1][2] = -2.0f*Nplane.b*Nplane.c; - pout.m[2][0] = -2.0f*Nplane.c*Nplane.a; - pout.m[2][1] = -2.0f*Nplane.c*Nplane.b; - pout.m[2][2] = 1.0f - 2.0f*Nplane.c*Nplane.c; - pout.m[3][0] = -2.0f*Nplane.d*Nplane.a; - pout.m[3][1] = -2.0f*Nplane.d*Nplane.b; - pout.m[3][2] = -2.0f*Nplane.d*Nplane.c; - } -//+------------------------------------------------------------------+ -//| Builds a matrix that rotates around an arbitrary axis. | -//+------------------------------------------------------------------+ -void DXMatrixRotationAxis(DXMatrix &out,const DXVector3 &v,float angle) - { - DXVector3 nv; - DXVec3Normalize(nv,v); -//--- - float sangle = (float)sin(angle); - float cangle = (float)cos(angle); - float cdiff = 1.0f - cangle; -//--- - out.m[0][0] = cdiff*nv.x*nv.x + cangle; - out.m[1][0] = cdiff*nv.x*nv.y - sangle*nv.z; - out.m[2][0] = cdiff*nv.x*nv.z + sangle*nv.y; - out.m[3][0] = 0.0f; - out.m[0][1] = cdiff*nv.y*nv.x + sangle*nv.z; - out.m[1][1] = cdiff*nv.y*nv.y + cangle; - out.m[2][1] = cdiff*nv.y*nv.z - sangle*nv.x; - out.m[3][1] = 0.0f; - out.m[0][2] = cdiff*nv.z*nv.x - sangle*nv.y; - out.m[1][2] = cdiff*nv.z*nv.y + sangle*nv.x; - out.m[2][2] = cdiff*nv.z*nv.z + cangle; - out.m[3][2] = 0.0f; - out.m[0][3] = 0.0f; - out.m[1][3] = 0.0f; - out.m[2][3] = 0.0f; - out.m[3][3] = 1.0f; - } -//+------------------------------------------------------------------+ -//| Builds a rotation matrix from a quaternion. | -//+------------------------------------------------------------------+ -void DXMatrixRotationQuaternion(DXMatrix &pout,const DXQuaternion &pq) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = 1.0f - 2.0f*(pq.y*pq.y + pq.z*pq.z); - pout.m[0][1] = 2.0f*(pq.x*pq.y + pq.z*pq.w); - pout.m[0][2] = 2.0f*(pq.x*pq.z - pq.y*pq.w); - pout.m[1][0] = 2.0f*(pq.x*pq.y - pq.z*pq.w); - pout.m[1][1] = 1.0f - 2.0f * (pq.x*pq.x + pq.z*pq.z); - pout.m[1][2] = 2.0f*(pq.y*pq.z + pq.x*pq.w); - pout.m[2][0] = 2.0f*(pq.x*pq.z + pq.y*pq.w); - pout.m[2][1] = 2.0f*(pq.y*pq.z - pq.x*pq.w); - pout.m[2][2] = 1.0f - 2.0f*(pq.x*pq.x + pq.y*pq.y); - } -//+------------------------------------------------------------------+ -//| Builds a matrix that rotates around the x-axis. | -//+------------------------------------------------------------------+ -void DXMatrixRotationX(DXMatrix &pout,float angle) - { - DXMatrixIdentity(pout); -//--- - pout.m[1][1] = (float)cos(angle); - pout.m[2][2] = (float)cos(angle); - pout.m[1][2] = (float)sin(angle); - pout.m[2][1] = -(float)sin(angle); - } -//+------------------------------------------------------------------+ -//| Builds a matrix that rotates around the y-axis. | -//+------------------------------------------------------------------+ -void DXMatrixRotationY(DXMatrix &pout,float angle) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = (float)cos(angle); - pout.m[2][2] = (float)cos(angle); - pout.m[0][2] = -(float)sin(angle); - pout.m[2][0] = (float)sin(angle); - } -//+------------------------------------------------------------------+ -//| Builds a matrix with a specified yaw, pitch, and roll. | -//+------------------------------------------------------------------+ -//| The order of transformations is roll first, then pitch, then yaw.| -//| Relative to the object's local coordinate axis, this is | -//| equivalent to rotation around the z-axis, followed by rotation | -//| around the x-axis, followed by rotation around the y-axis. | -//+------------------------------------------------------------------+ -void DXMatrixRotationYawPitchRoll(DXMatrix &out,float yaw,float pitch,float roll) - { - float sroll = (float)sin(roll); - float croll = (float)cos(roll); - float spitch = (float)sin(pitch); - float cpitch = (float)cos(pitch); - float syaw = (float)sin(yaw); - float cyaw = (float)cos(yaw); -//--- - out.m[0][0] = sroll * spitch * syaw + croll * cyaw; - out.m[0][1] = sroll * cpitch; - out.m[0][2] = sroll * spitch * cyaw - croll * syaw; - out.m[0][3] = 0.0f; - out.m[1][0] = croll * spitch * syaw - sroll * cyaw; - out.m[1][1] = croll * cpitch; - out.m[1][2] = croll * spitch * cyaw + sroll * syaw; - out.m[1][3] = 0.0f; - out.m[2][0] = cpitch * syaw; - out.m[2][1] = -spitch; - out.m[2][2] = cpitch * cyaw; - out.m[2][3] = 0.0f; - out.m[3][0] = 0.0f; - out.m[3][1] = 0.0f; - out.m[3][2] = 0.0f; - out.m[3][3] = 1.0f; - } -//+------------------------------------------------------------------+ -//| Builds a matrix that rotates around the z-axis. | -//+------------------------------------------------------------------+ -void DXMatrixRotationZ(DXMatrix &pout,float angle) - { - DXMatrixIdentity(pout); -//--- - pout.m[0][0] = (float)cos(angle); - pout.m[1][1] = (float)cos(angle); - pout.m[0][1] = (float)sin(angle); - pout.m[1][0] = -(float)sin(angle); - } -//+------------------------------------------------------------------+ -//| Builds a matrix that scales along the x-axis, | -//| the y-axis,and the z-axis. | -//+------------------------------------------------------------------+ -void DXMatrixScaling(DXMatrix &pout,float sx,float sy,float sz) - { - DXMatrixIdentity(pout); - pout.m[0][0] = sx; - pout.m[1][1] = sy; - pout.m[2][2] = sz; - } -//+------------------------------------------------------------------+ -//| Builds a matrix that flattens geometry into a plane. | -//+------------------------------------------------------------------+ -//| The DXMatrixShadow function flattens geometry into a plane, as | -//| if casting a shadow from a light. | -//| This function uses the following formula to compute the returned | -//| matrix. | -//| | -//| P = normalize(Plane); | -//| L = Light; | -//| d = -dot(P,L) | -//| | -//| P.a * L.x + d P.a * L.y P.a * L.z P.a * L.w | -//| P.b * L.x P.b * L.y + d P.b * L.z P.b * L.w | -//| P.c * L.x P.c * L.y P.c * L.z + d P.c * L.w | -//| P.d * L.x P.d * L.y P.d * L.z P.d * L.w + d | -//| | -//| If the light's w-component is 0, the ray from the origin to the | -//| light represents a directional light. If it is 1,the light is | -//| a point light. | -//+------------------------------------------------------------------+ -void DXMatrixShadow(DXMatrix &pout,const DXVector4 &plight,const DXPlane &pplane) - { - DXPlane Nplane; - DXPlaneNormalize(Nplane,pplane); - float dot = DXPlaneDot(Nplane,plight); -//--- - pout.m[0][0] = dot - Nplane.a*plight.x; - pout.m[0][1] = -Nplane.a*plight.y; - pout.m[0][2] = -Nplane.a*plight.z; - pout.m[0][3] = -Nplane.a*plight.w; - pout.m[1][0] = -Nplane.b*plight.x; - pout.m[1][1] = dot - Nplane.b*plight.y; - pout.m[1][2] = -Nplane.b*plight.z; - pout.m[1][3] = -Nplane.b*plight.w; - pout.m[2][0] = -Nplane.c*plight.x; - pout.m[2][1] = -Nplane.c*plight.y; - pout.m[2][2] = dot - Nplane.c*plight.z; - pout.m[2][3] = -Nplane.c*plight.w; - pout.m[3][0] = -Nplane.d*plight.x; - pout.m[3][1] = -Nplane.d*plight.y; - pout.m[3][2] = -Nplane.d*plight.z; - pout.m[3][3] = dot - Nplane.d*plight.w; - } -//+------------------------------------------------------------------+ -//| Builds a transformation matrix. | -//+------------------------------------------------------------------+ -//| This function calculates the transformation matrix with the | -//| following formula, with matrix concatenation evaluated | -//| in left-to-right order: | -//| | -//| Mout = (Msc)^(-1)*(Msr)^(-1)*Ms*Msr*Msc*(Mrc)^(-1)*Mr*Mrc*Mt | -//| | -//| where: | -//| Mout = output matrix (pOut) | -//| Msc = scaling center matrix (pScalingCenter) | -//| Msr = scaling rotation matrix (pScalingRotation) | -//| Ms = scaling matrix (pScaling) | -//| Mrc = center of rotation matrix (pRotationCenter) | -//| Mr = rotation matrix (pRotation) | -//| Mt = translation matrix (pTranslation) | -//+------------------------------------------------------------------+ -void DXMatrixTransformation(DXMatrix &pout,const DXVector3 &pscalingcenter,const DXQuaternion &pscalingrotation,const DXVector3 &pscaling,const DXVector3 &protationcenter,const DXQuaternion &protation,const DXVector3 &ptranslation) - { - DXMatrix m1,m2,m3,m4,m5,m6,m7; - DXQuaternion prc; - DXVector3 psc,pt; -//--- pscalingcenter - psc.x = pscalingcenter.x; - psc.y = pscalingcenter.y; - psc.z = pscalingcenter.z; -//--- protationcenter - prc.x = protationcenter.x; - prc.y = protationcenter.y; - prc.z = protationcenter.z; -//--- ptranslation - pt.x = ptranslation.x; - pt.y = ptranslation.y; - pt.z = ptranslation.z; - DXMatrixTranslation(m1,-psc.x,-psc.y,-psc.z); -//--- - DXQuaternion temp; - DXMatrixRotationQuaternion(m4,pscalingrotation); - temp.w = pscalingrotation.w; - temp.x = -pscalingrotation.x; - temp.y = -pscalingrotation.y; - temp.z = -pscalingrotation.z; - DXMatrixRotationQuaternion(m2,temp); -//--- pscaling - DXMatrixScaling(m3,pscaling.x,pscaling.y,pscaling.z); -//--- protation - DXMatrixRotationQuaternion(m6,protation); -//--- - DXMatrixTranslation(m5,psc.x - prc.x,psc.y - prc.y,psc.z - prc.z); - DXMatrixTranslation(m7,prc.x + pt.x,prc.y + pt.y,prc.z + pt.z); - DXMatrixMultiply(m1,m1,m2); - DXMatrixMultiply(m1,m1,m3); - DXMatrixMultiply(m1,m1,m4); - DXMatrixMultiply(m1,m1,m5); - DXMatrixMultiply(m1,m1,m6); - DXMatrixMultiply(pout,m1,m7); - } -//+------------------------------------------------------------------+ -//| Builds a 2D transformation matrix that represents | -//| transformations in the xy plane. | -//+------------------------------------------------------------------+ -//| This function calculates the transformation matrix with the | -//| following formula, with matrix concatenation evaluated | -//| in left-to-right order: | -//| | -//| Mout = (Msc)^(-1)*(Msr)^(-1)*Ms*Msr*Msc*(Mrc)^(-1)*Mr*Mrc*Mt | -//| | -//| where: | -//| Mout = output matrix (pOut) | -//| Msc = scaling center matrix (pScalingCenter) | -//| Msr = scaling rotation matrix (pScalingRotation) | -//| Ms = scaling matrix (pScaling) | -//| Mrc = center of rotation matrix (pRotationCenter) | -//| Mr = rotation matrix (Rotation) | -//| Mt = translation matrix (pTranslation) | -//+------------------------------------------------------------------+ -void DXMatrixTransformation2D(DXMatrix &pout,const DXVector2 &pscalingcenter,float scalingrotation,const DXVector2 &pscaling,const DXVector2 &protationcenter,float rotation,const DXVector2 &ptranslation) - { - DXQuaternion rot,sca_rot; - DXVector3 rot_center,sca,sca_center,trans; -//--- pscalingcenter - sca_center.x=pscalingcenter.x; - sca_center.y=pscalingcenter.y; - sca_center.z=0.0f; -//--- pscaling - sca.x=pscaling.x; - sca.y=pscaling.y; - sca.z=1.0f; -//--- protationcenter - rot_center.x=protationcenter.x; - rot_center.y=protationcenter.y; - rot_center.z=0.0f; -//--- ptranslation - trans.x=ptranslation.x; - trans.y=ptranslation.y; - trans.z=0.0f; -//--- - rot.w=(float)cos(rotation/2.0f); - rot.x=0.0f; - rot.y=0.0f; - rot.z=(float)sin(rotation/2.0f); -//--- - sca_rot.w=(float)cos(scalingrotation/2.0f); - sca_rot.x=0.0f; - sca_rot.y=0.0f; - sca_rot.z=(float)sin(scalingrotation/2.0f); - DXMatrixTransformation(pout,sca_center,sca_rot,sca,rot_center,rot,trans); - } -//+------------------------------------------------------------------+ -//| Builds a matrix using the specified offsets. | -//+------------------------------------------------------------------+ -void DXMatrixTranslation(DXMatrix &pout,float x,float y,float z) - { - DXMatrixIdentity(pout); -//--- - pout.m[3][0] = x; - pout.m[3][1] = y; - pout.m[3][2] = z; - } -//+------------------------------------------------------------------+ -//| Returns the matrix transpose of a matrix. | -//+------------------------------------------------------------------+ -void DXMatrixTranspose(DXMatrix &pout,const DXMatrix &pm) - { - const DXMatrix m = pm; - for(int i=0; i<4; i++) - for(int j=0; j<4; j++) - pout.m[i][j] = m.m[j][i]; - } -//+------------------------------------------------------------------+ -//| Computes the dot product of a plane and a 4D vector. | -//+------------------------------------------------------------------+ -float DXPlaneDot(const DXPlane &p1,const DXVector4 &p2) - { - return(p1.a*p2.x + p1.b*p2.y + p1.c*p2.z + p1.d*p2.w); - } -//+------------------------------------------------------------------+ -//| Computes the dot product of a plane and a 3D vector. | -//| The w parameter of the vector is assumed to be 1. | -//+------------------------------------------------------------------+ -float DXPlaneDotCoord(const DXPlane &pp,const DXVector4 &pv) - { - return(pp.a*pv.x + pp.b*pv.y + pp.c*pv.z + pp.d); - } -//+------------------------------------------------------------------+ -//| Computes the dot product of a plane and a 3D vector. | -//| The w parameter of the vector is assumed to be 0. | -//+------------------------------------------------------------------+ -float DXPlaneDotNormal(const DXPlane &pp,const DXVector4 &pv) - { - return(pp.a*pv.x + pp.b*pv.y + pp.c*pv.z); - } -//+------------------------------------------------------------------+ -//| Constructs a plane from a point and a normal. | -//+------------------------------------------------------------------+ -void DXPlaneFromPointNormal(DXPlane &pout,const DXVector3 &pvpoint,const DXVector3 &pvnormal) - { - pout.a = pvnormal.x; - pout.b = pvnormal.y; - pout.c = pvnormal.z; - pout.d = -DXVec3Dot(pvpoint,pvnormal); - } -//+------------------------------------------------------------------+ -//| Constructs a plane from three points. | -//+------------------------------------------------------------------+ -void DXPlaneFromPoints(DXPlane &pout,const DXVector3 &pv1,const DXVector3 &pv2,const DXVector3 &pv3) - { - DXVector3 edge1,edge2,normal,Nnormal; -//--- - edge1.x = 0.0f; - edge1.y = 0.0f; - edge1.z = 0.0f; - edge2.x = 0.0f; - edge2.y = 0.0f; - edge2.z = 0.0f; -//--- - DXVec3Subtract(edge1,pv2,pv1); - DXVec3Subtract(edge2,pv3,pv1); - DXVec3Cross(normal,edge1,edge2); - DXVec3Normalize(Nnormal,normal); - DXPlaneFromPointNormal(pout,pv1,Nnormal); - } -//+------------------------------------------------------------------+ -//| Finds the intersection between a plane and a line. | -//| If the line is parallel to the plane, null vector is returned. | -//+------------------------------------------------------------------+ -void DXPlaneIntersectLine(DXVector3 &pout,const DXPlane &pp,const DXVector3 &pv1,const DXVector3 &pv2) - { - DXVector3 direction,normal; - normal.x = pp.a; - normal.y = pp.b; - normal.z = pp.c; - direction.x = pv2.x - pv1.x; - direction.y = pv2.y - pv1.y; - direction.z = pv2.z - pv1.z; -//--- - float dot = DXVec3Dot(normal,direction); - if(!dot) - { - pout.x=0.0f; - pout.y=0.0f; - pout.z=0.0f; - } - float temp = (pp.d + DXVec3Dot(normal,pv1))/dot; - pout.x = pv1.x - temp*direction.x; - pout.y = pv1.y - temp*direction.y; - pout.z = pv1.z - temp*direction.z; - } -//+------------------------------------------------------------------+ -//| Normalizes the plane coefficients so that the plane normal | -//| has unit length. | -//| This function normalizes a plane so that |a,b,c| == 1. | -//+------------------------------------------------------------------+ -void DXPlaneNormalize(DXPlane &out,const DXPlane &p) - { - float norm = (float)sqrt(p.a*p.a + p.b*p.b + p.c*p.c); - if(norm) - { - out.a = p.a/norm; - out.b = p.b/norm; - out.c = p.c/norm; - out.d = p.d/norm; - } - else - { - out.a = 0.0f; - out.b = 0.0f; - out.c = 0.0f; - out.d = 0.0f; - } - } -//+------------------------------------------------------------------+ -//| Scale the plane with the given scaling factor. | -//+------------------------------------------------------------------+ -void DXPlaneScale(DXPlane &pout,const DXPlane &p,float s) - { - pout.a = p.a*s; - pout.b = p.b*s; - pout.c = p.c*s; - pout.d = p.d*s; - }; -//+------------------------------------------------------------------+ -//| Transforms a plane by a matrix. | -//| The input matrix is the inverse transpose of the actual | -//| transformation. | -//+------------------------------------------------------------------+ -void DXPlaneTransform(DXPlane &pout,const DXPlane &pplane,const DXMatrix &pm) - { - DXPlane plane = pplane; -//--- - pout.a = pm.m[0][0]*plane.a + pm.m[1][0]*plane.b + pm.m[2][0]*plane.c + pm.m[3][0]*plane.d; - pout.b = pm.m[0][1]*plane.a + pm.m[1][1]*plane.b + pm.m[2][1]*plane.c + pm.m[3][1]*plane.d; - pout.c = pm.m[0][2]*plane.a + pm.m[1][2]*plane.b + pm.m[2][2]*plane.c + pm.m[3][2]*plane.d; - pout.d = pm.m[0][3]*plane.a + pm.m[1][3]*plane.b + pm.m[2][3]*plane.c + pm.m[3][3]*plane.d; - } -//+------------------------------------------------------------------+ -//| Adds two spherical harmonic (SH) vectors; in other words, | -//| out[i] = a[i] + b[i]. | -//+------------------------------------------------------------------+ -//| Each coefficient of the basis function Y(l,m) is stored | -//| at memory location l^2 + m + l,where: | -//| l is the degree of the basis function. | -//| m is the basis function index for the given l value | -//| and ranges from -l to l, inclusive. | -//+------------------------------------------------------------------+ -void DXSHAdd(float &out[],int order,const float &a[],const float &b[]) - { - for(int i = 0; i DX_PI/2.0f) ? (DX_PI/2.0f) : radius; - float norm = (float)sin(clamped_angle)*(float)sin(clamped_angle); - if(order > DXSH_MAXORDER) - { - //--- order clamped at DXSH_MAXORDER - order = DXSH_MAXORDER; - } -//--- - weightedcapintegrale(cap,order,radius); - DXSHEvalDirection(rout,order,dir); -//--- - for(int i = 0; i DXSH_MAXORDER)) - return; - - out[0] = 0.5f/(float)sqrt(DX_PI); - out[1] = -0.5f/(float)sqrt(DX_PI/3.0f)*dir.y; - out[2] = 0.5f/(float)sqrt(DX_PI/3.0f)*dir.z; - out[3] = -0.5f/(float)sqrt(DX_PI/3.0f)*dir.x; - if(order == 2) - return; - - out[4] = 0.5f/(float)sqrt(DX_PI/15.0f)*dirxy; - out[5] = -0.5f/(float)sqrt(DX_PI/15.0f)*diryz; - out[6] = 0.25f/(float)sqrt(DX_PI/5.0f)*(3.0f*dirzz - 1.0f); - out[7] = -0.5f/(float)sqrt(DX_PI/15.0f)*dirxz; - out[8] = 0.25f/(float)sqrt(DX_PI/15.0f)*(dirxx - diryy); - if(order == 3) - return; - - out[9] = -(float)sqrt(70.0f/DX_PI)/8.0f*dir.y*(3.0f*dirxx - diryy); - out[10] = (float)sqrt(105.0f/DX_PI)/2.0f*dirxy*dir.z; - out[11] = -(float)sqrt(42.0f/DX_PI)/8.0f*dir.y*(-1.0f + 5.0f*dirzz); - out[12] = (float)sqrt(7.0f/DX_PI)/4.0f*dir.z*(5.0f*dirzz - 3.0f); - out[13] = (float)sqrt(42.0f/DX_PI)/8.0f*dir.x*(1.0f - 5.0f*dirzz); - out[14] = (float)sqrt(105.0f/DX_PI)/4.0f*dir.z*(dirxx - diryy); - out[15] = -(float)sqrt(70.0f/DX_PI)/8.0f*dir.x*(dirxx - 3.0f*diryy); - if(order == 4) - return; - - out[16] = 0.75f*float(sqrt(35.0f/DX_PI))*dirxy*(dirxx - diryy); - out[17] = 3.0f*dir.z*out[9]; - out[18] = 0.75f*(float)sqrt(5.0f/DX_PI)*dirxy*(7.0f*dirzz - 1.0f); - out[19] = 0.375f*(float)sqrt(10.0f/DX_PI)*diryz*(3.0f - 7.0f*dirzz); - out[20] = 3.0f/(16.0f*(float)sqrt(DX_PI))*(35.0f*dirzzzz - 30.f*dirzz + 3.0f); - out[21] = 0.375f*(float)sqrt(10.0f/DX_PI)*dirxz*(3.0f - 7.0f*dirzz); - out[22] = 0.375f*(float)sqrt(5.0f/DX_PI)*(dirxx - diryy)*(7.0f*dirzz - 1.0f); - out[23] = 3.0f*dir.z*out[15]; - out[24] = 3.0f / 16.0f*float(sqrt(35.0f/DX_PI))*(dirxxxx - 6.0f*dirxyxy + diryyyy); - if(order == 5) - return; - - out[25] = -3.0f/32.0f*(float)sqrt(154.0f/DX_PI)*dir.y*(5.0f*dirxxxx - 10.0f*dirxyxy + diryyyy); - out[26] = 0.75f*(float)sqrt(385.0f/DX_PI)*dirxy*dir.z*(dirxx - diryy); - out[27] = (float)sqrt(770.0f/DX_PI)/32.0f*dir.y*(3.0f*dirxx - diryy)*(1.0f - 9.0f*dirzz); - out[28] = (float)sqrt(1155.0f/DX_PI)/4.0f*dirxy*dir.z*(3.0f*dirzz - 1.0f); - out[29] = (float)sqrt(165.0f/DX_PI)/16.0f*dir.y*(14.0f*dirzz - 21.0f*dirzzzz - 1.0f); - out[30] = (float)sqrt(11.0f/DX_PI)/16.0f*dir.z*(63.0f*dirzzzz - 70.0f*dirzz + 15.0f); - out[31] = (float)sqrt(165.0f/DX_PI)/16.0f*dir.x*(14.0f*dirzz - 21.0f*dirzzzz - 1.0f); - out[32] = (float)sqrt(1155.0f/DX_PI)/8.0f*dir.z*(dirxx - diryy)*(3.0f*dirzz - 1.0f); - out[33] = (float)sqrt(770.0f/DX_PI)/32.0f*dir.x*(dirxx - 3.0f*diryy)*(1.0f - 9.0f*dirzz); - out[34] = 3.0f/16.0f*(float)sqrt(385.0f/DX_PI)*dir.z*(dirxxxx - 6.0f*dirxyxy + diryyyy); - out[35] = -3.0f/32.0f*(float)sqrt(154.0f/DX_PI)*dir.x*(dirxxxx - 10.0f*dirxyxy + 5.0f*diryyyy); - } -//+------------------------------------------------------------------+ -//| Evaluates a directional light and | -//| returns spectral spherical harmonic (SH) data. | -//+------------------------------------------------------------------+ -//| The output vector is computed so that if the intensity ratio | -//| R/G/B is equal to 1 ,the resulting exit radiance of a point | -//| directly under the light on a diffuse object with an albedo | -//| of 1 would be 1.0. This will compute three spectral samples; | -//| rout[], gout[] and bout[] will be returned. | -//+------------------------------------------------------------------+ -int DXSHEvalDirectionalLight(int order,const DXVector3 &dir,float Rintensity,float Gintensity,float Bintensity,float &rout[],float &gout[],float &bout[]) - { - float s = 0.75f; - if(order > 2) - s += 5.0f/16.0f; - if(order > 4) - s -= 3.0f/32.0f; - s /= DX_PI; - - DXSHEvalDirection(rout,order,dir); - for(int j=0; j DXSH_MAXORDER) - order = DXSH_MAXORDER; -//--- check radius - if(radius < 0.0f) - radius = -radius; - - float dist = DXVec3Length(dir); - float clamped_angle = (dist <= radius) ? DX_PI/2.0f : (float)asin(radius / dist); - - weightedcapintegrale(cap,order,clamped_angle); - DXVec3Normalize(normal,dir); - DXSHEvalDirection(rout,order,normal); - - for(int i=0; iDXSH_MAXORDER) || (order0; j--) - { - out[sum - j] = 0.0f; - out[sum - j] = c[j - 1]*in[sum - j]; - out[sum - j] += s[j - 1]*in[sum + j]; - } - out[sum] = in[sum]; - //--- - for(int j=1; j(); - if(m_buffer_object!=NULL) - { - m_buffer_object.AddRef(); - //--- use default vertex shader - m_shader_vertex=dispatcher.ShaderCreateDefault(DX_SHADER_VERTEX); - if(m_shader_vertex!=NULL) - { - m_shader_vertex.AddRef(); - //--- use default pixel shader - m_shader_pixel=dispatcher.ShaderCreateDefault(DX_SHADER_PIXEL); - if(m_shader_pixel!=NULL) - { - m_shader_pixel.AddRef(); - //--- create vertex buffer - m_buffer_vertex=dispatcher.VertexBufferCreate(vertices); - if(m_buffer_vertex!=NULL) - { - m_buffer_vertex.AddRef(); - //--- create index buffer - m_buffer_index=dispatcher.IndexBufferCreate(indices); - if(m_buffer_index!=NULL) - m_buffer_index.AddRef(); - } - } - } - } - //--- set object buffer to shaders - if(m_buffer_object==NULL || m_shader_vertex==NULL || m_shader_pixel==NULL || m_buffer_vertex==NULL || m_buffer_index==NULL) - { - Shutdown(); - return(false); - } - //--- save scene buffer - m_buffer_scene=buffer_scene; - m_buffer_scene.AddRef(); - //--- save topology - m_topology=topology; - //--- - return(true); - } - //+------------------------------------------------------------------+ - //| Create mesh object from OBJ mesh file | - //+------------------------------------------------------------------+ - bool Create(CDXDispatcher &dispatcher,CDXInput* buffer_scene,string obj_path,float scale=1.0f,bool inverse_winding=false) - { - DXVertex vertices[]; - uint indices[]; - //--- load model - if(!DXLoadObjModel(obj_path,vertices,indices,scale)) - return(false); - //--- set white vertices color - DXColor white=DXColor(1.0f,1.0f,1.0f,1.0f); - int count=ArraySize(vertices); - for(int i=0; i -void DXInverseWinding(TVertex &vertices[],uint &indices[]) - { -//--- proccess vertices - uint count=ArraySize(vertices); - for(uint i=0; i0) - faces[idx].v[i]=(int)StringToInteger(str_parsed_faces[0]); - if(elements>1) - faces[idx].t[i]=(int)StringToInteger(str_parsed_faces[1]); - if(elements>2) - faces[idx].n[i]=(int)StringToInteger(str_parsed_faces[2]); - } - //--- debug message - if(show_debug) - printf("%face d: %d vertex(%d,%d,%d,%d) texture(%d,%d,%d,%d) normal(%d,%d,%d,%d)",idx+1, - faces[idx].v[0],faces[idx].v[1],faces[idx].v[2],faces[idx].v[3], - faces[idx].t[0],faces[idx].t[1],faces[idx].t[2],faces[idx].t[3], - faces[idx].n[0],faces[idx].n[1],faces[idx].n[2],faces[idx].n[3]); - //--- - break; - } - - default: - { - break; - } - } - } -//--- close the file - FileClose(file_handle); -//--- - if(show_debug) - { - printf("File %s loaded successfully. Total lines: %d",filename,total_lines); - printf("total v_positions=%d",total_positions); - printf("total v_normals=%d",total_normals); - printf("total v_tcoords=%d",total_tcoords); - printf("total faces=%d",total_faces); - } -//--- - return(true); - } -//+------------------------------------------------------------------+ -//| Load static 3D models from Maya 2011 | -//| https://en.wikibooks.org/wiki/DirectX/10.0/Direct3D/Loading_Maya | -//| TVertex must have | -//| DXVector4 position, normal and DXVector2 tcoord members | -//+------------------------------------------------------------------+ -template -bool DXLoadObjModel(const string filename,TVertex &vertices[],uint &indices[],float scale=1.0f) - { -//--- intermediate data arrays - DXVector4 v_positions[]; - DXVector2 v_tcoords[]; - DXVector4 v_normals[]; - OBJFaceType faces[]; -//--- load data - if(!DXLoadObjData(filename,v_positions,v_tcoords,v_normals,faces,false)) - { - printf("Error loading model data from %s",filename); - return(false); - } -//--- - int total_v_positions=ArraySize(v_positions); - int total_v_tcoords =ArraySize(v_tcoords); - int total_v_normals =ArraySize(v_normals); - int total_faces =ArraySize(faces); -//--- check faces - if(total_faces==0) - { - printf("No model data."); - return(false); - } -//--- check consistency of the indices - int vertices_count=0; - int indices_count =0; - bool split_vertices=false; - for(int i=0; i4) - { - printf("Error in %d face, face vertices count is %d",i,faces[i].total); - return(false); - } - //--- - for(int j=0; jtotal_v_positions) - { - printf("Error in %d face, %d vertext index is %d. Total posiitons=%d",i,j,faces[i].v[j],total_v_positions); - return(false); - } - if(total_v_tcoords>0) - { - if(faces[i].t[j]<=0 || faces[i].t[j]>total_v_tcoords) - { - printf("Error in %d face, %d tcoord index is %d. Total tcoords=%d",i,j,faces[i].v[j],total_v_positions); - return(false); - } - if(faces[i].t[j]!=faces[i].v[j]) - split_vertices=true; - } - if(total_v_normals>0) - { - if(faces[i].n[j]<=0 || faces[i].n[j]>total_v_normals) - { - printf("Error in %d face, %d normal index is %d. Total normals=%d",i,j,faces[i].v[j],total_v_positions); - return(false); - } - if(faces[i].n[j]!=faces[i].v[j]) - split_vertices=true; - } - } - //--- calc counts - vertices_count+=faces[i].total; - if(faces[i].total<4) - indices_count+=3; - else - indices_count+=6; - } - printf("Data consistency checked."); -//--- prepare arrays - if(!split_vertices) - vertices_count=total_v_positions; - ArrayResize(vertices,vertices_count); - ArrayResize(indices, indices_count); - int v_idx=0,i_idx=0; - for(int i=0; i -bool DXComputeBox(const DXVector3 &from,const DXVector3 &to,TVertex &vertices[],uint &indices[]) - { -//--- prepare arrays - const int faces=6; - if(ArrayResize(vertices,4*faces)!=4*faces) - return(false); -//--- set indices - uint ind[]= {0,1,2, 2,3,0, 4,5,6, 6,7,4, 8,9,10, 10,11,8, 12,13,14, 14,15,12, 16,17,18, 18,19,16, 20,21,22, 22,23,20}; - ArrayResize(indices,0); - if(ArrayCopy(indices,ind)!=ArraySize(ind)) - return(false); -//--- prepare boundaries - float left=from.x,right=to.x,bottom=from.y,top=to.y,near=from.z,far=to.z; - if(from.x>to.x) - { - right=from.x; - left= to.x; - } - if(from.y>to.y) - { - top= from.y; - bottom=to.y; - } - if(from.z>to.z) - { - far=from.z; - near=to.z; - } -//--- left face - vertices[0].position=DXVector4(left,top, far, 1.0); - vertices[1].position=DXVector4(left,top, near,1.0); - vertices[2].position=DXVector4(left,bottom,near,1.0); - vertices[3].position=DXVector4(left,bottom,far, 1.0); - for(int i=0; i<4; i++) - vertices[i].normal=DXVector4(-1.0,0.0,0.0,0.0); -//--- right face - vertices[4].position=DXVector4(right,top, near,1.0); - vertices[5].position=DXVector4(right,top, far, 1.0); - vertices[6].position=DXVector4(right,bottom,far, 1.0); - vertices[7].position=DXVector4(right,bottom,near,1.0); - for(int i=4; i<8; i++) - vertices[i].normal=DXVector4(1.0,0.0,0.0,0.0); -//--- front face - vertices[8].position =DXVector4(left, top, near,1.0); - vertices[9].position =DXVector4(right,top, near,1.0); - vertices[10].position=DXVector4(right,bottom,near,1.0); - vertices[11].position=DXVector4(left, bottom,near,1.0); - for(int i=8; i<12; i++) - vertices[i].normal=DXVector4(0.0,0.0,-1.0,0.0); -//--- back face - vertices[12].position=DXVector4(right,top, far,1.0); - vertices[13].position=DXVector4(left, top, far,1.0); - vertices[14].position=DXVector4(left, bottom,far,1.0); - vertices[15].position=DXVector4(right,bottom,far,1.0); - for(int i=12; i<16; i++) - vertices[i].normal=DXVector4(0.0,0.0,1.0,0.0); -//--- top face - vertices[16].position=DXVector4(left, top,far, 1.0); - vertices[17].position=DXVector4(right,top,far, 1.0); - vertices[18].position=DXVector4(right,top,near,1.0); - vertices[19].position=DXVector4(left, top,near,1.0); - for(int i=16; i<20; i++) - vertices[i].normal=DXVector4(0.0,1.0,0.0,0.0); -//--- bottom face - vertices[20].position=DXVector4(left, bottom,near,1.0); - vertices[21].position=DXVector4(right,bottom,near,1.0); - vertices[22].position=DXVector4(right,bottom,far, 1.0); - vertices[23].position=DXVector4(left, bottom,far, 1.0); - for(int i=20; i<24; i++) - vertices[i].normal=DXVector4(0.0,-1.0,0.0,0.0); -//--- texture coordinates - for(int i=0; i -bool DXComputeSphere(float radius,uint tessellation,TVertex &vertices[],uint &indices[]) - { - if(tessellation<3) - tessellation=3; - uint segments_y =tessellation; - uint segments_xz=tessellation*2; -//--- prepare arrays - uint count=(segments_y+1)*(segments_xz+1); - if(ArrayResize(vertices,count)!=count) - return(false); - count=6*segments_y*(segments_xz); - if(ArrayResize(indices,count)!=count) - return(false); -//--- create rings of vertices at progressively higher latitudes. - for(uint i=0,idx=0; i<=segments_y; i++) - { - DXVector2 tcoord=DXVector2(0.0f,1.0f-(float)i/segments_y); - float latitude=(i*DX_PI/segments_y)-DX_PI_DIV2; - float dy =(float)sin(latitude); - float dxz=(float)cos(latitude); - //--- create a single ring of vertices at this latitude. - for(uint j=0; j<=segments_xz; j++,idx++) - { - float longitude=(j%segments_xz)*DX_PI_MUL2/segments_xz; - //--- normal - DXVector3 normal=DXVector3((float)sin(longitude)*dxz,dy,(float)cos(longitude)*dxz); - vertices[idx].normal =DXVector4(normal.x,normal.y,normal.z,0.0); - //--- position - DXVec3Scale(normal,normal,radius); - vertices[idx].position=DXVector4(normal.x,normal.y,normal.z,1.0); - //--- texture coords - tcoord.x = float(j)/segments_xz; - vertices[idx].tcoord =tcoord; - } - } -//--- fill the index buffer with triangles joining each pair of latitude rings. - uint stride=segments_xz+1; - uint idx=0; - for(uint i=0; i -bool DXComputeTorus(float outer_radius,float inner_radius,uint tessellation,TVertex &vertices[],uint &indices[]) - { - if(tessellation<3) - tessellation=3; -//--- prepare arrays - uint count=(tessellation+1)*(tessellation+1); - if(ArrayResize(vertices,count)!=count) - return(false); - count=6*tessellation*tessellation; - if(ArrayResize(indices,count)!=count) - return(false); -//--- - uint v=0,idx=0; - uint stride=tessellation+1; -//--- first we loop around the main ring of the torus. - for(uint i=0; i<=tessellation; i++) - { - DXVector2 tcoord=DXVector2(float(i)/tessellation,0.0f); - //--- create a transform matrix that will align geometry to slice perpendicularly though the current ring position. - DXMatrix rotation,transform; - DXMatrixRotationY(rotation,-1.0f*(i%tessellation)*DX_PI_MUL2/tessellation-DX_PI_DIV2); - DXMatrixTranslation(transform,outer_radius,0.0f,0.0f); - DXMatrixMultiply(transform,transform,rotation); - //--- now we loop along the other axis, around the side of the tube. - for(uint j=0; j<=tessellation; j++) - { - //--- calc normal and position - float angle=(j%tessellation)*DX_PI_MUL2/tessellation+DX_PI; - vertices[v].normal=DXVector4((float)cos(angle),(float)sin(angle),0.0f,0.0f); - vertices[v].position=DXVector4(vertices[v].normal.x*inner_radius,vertices[v].normal.y*inner_radius,0.0f,1.0f); - DXVec4Transform(vertices[v].normal, vertices[v].normal, transform); - DXVec4Transform(vertices[v].position,vertices[v].position,transform); - //--- calc texture coord - tcoord.y=1-float(j)/tessellation; - vertices[v].tcoord=tcoord; - v++; - //--- create indices for two triangles. - if(i -bool DXComputeCylinder(float radius,float height,uint tessellation,TVertex &vertices[],uint &indices[]) - { - return(DXComputeTruncatedCone(radius,radius,height,tessellation,vertices,indices)); - } -//+------------------------------------------------------------------+ -//| Truncated Cone | -//| TVertex must have | -//| DXVector4 position, DXVector4 normal and DXVector2 tcoord members| -//+------------------------------------------------------------------+ -template -bool DXComputeTruncatedCone(float radius_top,float radius_bottom,float height,uint tessellation,TVertex &vertices[],uint &indices[]) - { - if(tessellation<3) - tessellation=3; -//--- prepare arrays - uint count=2*(tessellation+1)+2*tessellation; - if(ArrayResize(vertices,count)!=count) - return(false); - count=6*tessellation+6*(tessellation-1); - if(ArrayResize(indices,count)!=count) - return(false); -//--- prepare normal - DXVector2 normal=DXVector2(height,radius_bottom-radius_top); - DXVec2Normalize(normal,normal); - float dy=height/2.0f; - uint v=0,idx=0; - uint stride=2; -//--- create top and bottom rings of vertices - for(uint i=0; i<=tessellation; i++) - { - float u=1.0f-(float)i/tessellation; - float angle=(i*DX_PI_MUL2/tessellation); - float dx=(float)sin(angle); - float dz=(float)cos(angle); - //--- - vertices[v].normal =DXVector4(dx*normal.x,normal.y,dz*normal.x,0.0f); - vertices[v].position=DXVector4(dx*radius_bottom,-dy,dz*radius_bottom,1.0f); - vertices[v].tcoord =DXVector2(u,1.0f); - v++; - vertices[v].normal =vertices[v-1].normal; - vertices[v].position=DXVector4(dx*radius_top,dy,dz*radius_top,1.0f); - vertices[v].tcoord =DXVector2(u,0.0f); - v++; - //--- creater side surface - if(i0 && i -bool DXComputeCone(float radius,float height,uint tessellation,TVertex &vertices[],uint &indices[]) - { - if(tessellation<3) - tessellation=3; -//--- prepare arrays - uint count=2*(tessellation+1)+tessellation; - if(ArrayResize(vertices,count)!=count) - return(false); - count=3*tessellation+3*(tessellation-1); - if(ArrayResize(indices,count)!=count) - return(false); -//--- prepare normal - DXVector2 normal=DXVector2(height,radius); - DXVec2Normalize(normal,normal); - float dy=height/2.0f; - uint v=0,idx=0; - uint stride=2; -//--- create top and bottom rings of vertices - for(uint i=0; i<=tessellation; i++) - { - float u=1.0f-(float)i/tessellation; - float angle=(i*DX_PI_MUL2/tessellation); - float dx=(float)sin(angle); - float dz=(float)cos(angle); - //--- - vertices[v].normal =DXVector4(dx*normal.x,normal.y,dz*normal.x,0.0f); - vertices[v].position=DXVector4(dx*radius,-dy,dz*radius,1.0f); - vertices[v].tcoord =DXVector2(u,1.0f); - v++; - vertices[v].normal =vertices[v-1].normal; - vertices[v].position=DXVector4(0.0f,dy,0.0f,1.0f); - vertices[v].tcoord =DXVector2(u,0.0f); - v++; - //--- creater side surface - if(i0 && i -bool DXComputeSurface(double &data[],uint data_width,uint data_height,double data_range, - const DXVector3 &from,const DXVector3 &to,DXVector2 &texture_size, - bool two_sided,bool use_normals, - TVertex &vertices[],uint &indices[]) - { -//--- - if(data_width<2 || data_height<2) - return(false); -//--- prepare arrays for vertices and triangles - uint count=data_width*data_height*(two_sided?2:1); - if(!ArrayResize(vertices,count)) - return(false); - count=6*(data_width-1)*(data_height-1)*(two_sided?2:1); - if(!ArrayResize(indices,count)) - return(false); -//--- find min and max value - float min_value=+FLT_MAX; - float max_value=-FLT_MAX; - for(uint j=0; jvalue) - min_value=value; - if(max_value=data_width-1) - DXVec4Subtract(v1,vertices[j*data_width+i-1].position,vertices[j*data_width+i].position); - else - DXVec4Subtract(v1,vertices[j*data_width+i-1].position,vertices[j*data_width+i+1].position); - //--- v2 - if(j<=0) - DXVec4Subtract(v2,vertices[j*data_width+i].position,vertices[(j+1)*data_width+i].position); - else - if(j>=data_height-1) - DXVec4Subtract(v2,vertices[(j-1)*data_width+i].position,vertices[j*data_width+i].position); - else - DXVec4Subtract(v2,vertices[(j-1)*data_width+i].position,vertices[(j+1)*data_width+i].position); - //--- normal - DXVec4Cross(normal,v2,v1,DXVector4(0.0f,0.0f,0.0f,1.0f)); - float inv_len=(float)(1.0/sqrt(normal.x*normal.x+normal.y*normal.y+normal.z*normal.z)); - vertices[j*data_width+i].normal.x=normal.x*inv_len; - vertices[j*data_width+i].normal.y=normal.y*inv_len; - vertices[j*data_width+i].normal.z=normal.z*inv_len; - vertices[j*data_width+i].normal.w=0.0f; - } - } - } - else - { - DXVector4 n=DXVector4(0.0f,0.0f,0.0f,0.0f); - for(int i=0; i blue > light blue > green > yellow > red > dark red | -//+---------------------------------------------------------------------+ -void DXComputeColorJet(const float value,DXColor &cout) - { - float v=value*1.1f-0.05f; - cout.r = fmin(fmax(v<0.75f ? 4*v-1.5f : 4.5f-4*v,0.0f),1.0f); - cout.g = fmin(fmax(v<0.5f ? 4*v-0.5f : 3.5f-4*v,0.0f),1.0f); - cout.b = fmin(fmax(v<0.25f ? 4*v+0.5f : 2.5f-4*v,0.0f),1.0f); - cout.a = 1.0; - } -//+---------------------------------------------------------------------+ -//| Computes hot to cold color scheme colors on [0;1] range | -//| blue > light blue > green > yellow > red | -//+---------------------------------------------------------------------+ -void DXComputeColorColdToHot(const float value,DXColor &cout) - { - float v=2*value-1.0f; - cout.r = fmin(fmax(2*v,0.0f),1.0f); - cout.g = fmin(fmax(2.0f-2*fabs(v),0.0f),1.0f); - cout.b = fmin(fmax(-2*v,0.0f),1.0f); - cout.a = 1.0; - } -//+---------------------------------------------------------------------+ -//| Computes red to green color scheme colors on [0;1] range | -//| red > yellow > dark green | -//+---------------------------------------------------------------------+ -void DXComputeColorRedToGreen(const float value,DXColor &cout) - { - if(value<=0.5) - { - cout.r=1.0f; - cout.g=DXScalarLerp(0.01f,0.95f,fmin(fmax(2*value,0.0f),1.0f)); - } - else - { - cout.r=DXScalarLerp(0.1f,1.0f, fmin(fmax(2.0f-2*value,0.0f),1.0f)); - cout.g=DXScalarLerp(0.6f,0.95f,fmin(fmax(2.0f-2*value,0.0f),1.0f)); - } - cout.b=0.0f; - cout.a=1.0f; - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/DX/Shaders/DefaultShaderPixel.hlsl b/Include/Canvas/DX/Shaders/DefaultShaderPixel.hlsl deleted file mode 100644 index ce90df8..0000000 --- a/Include/Canvas/DX/Shaders/DefaultShaderPixel.hlsl +++ /dev/null @@ -1,71 +0,0 @@ -//+------------------------------------------------------------------+ -//| Default Pixel Shader | -//| Copyright 2019, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ -//| Inputs for whole scene | -//+------------------------------------------------------------------+ -cbuffer InputScene : register(b0) - { - matrix view; - matrix projection; - float4 light_direction; - float4 light_color; - float4 ambient_color; - }; -//+------------------------------------------------------------------+ -//| Inputs for single object | -//+------------------------------------------------------------------+ -cbuffer InputObject : register(b1) - { - matrix transform; - float4 diffuse_color; - float4 emission_color; - float4 specular_color; - float specular_power; - float dummy[3]; - }; -//+------------------------------------------------------------------+ -//| Input texture | -//+------------------------------------------------------------------+ -Texture2D diffuse_tex : register(t0); -//+------------------------------------------------------------------+ -//| Texture sampler | -//+------------------------------------------------------------------+ -SamplerState diffuse_samp - { - Filter =MIN_MAG_MIP_LINEAR; - AddressU=Wrap; - AddressV=Wrap; - }; -//+------------------------------------------------------------------+ -//| Pixel shader input type | -//+------------------------------------------------------------------+ -struct PSInput - { - float4 position : SV_POSITION; - float4 camera : CAMERA; - float4 normal : NORMAL; - float2 tcoord : TEXCOORD; - float4 color : COLOR; - }; -//+------------------------------------------------------------------+ -//| Pixel shader entry point | -//+------------------------------------------------------------------+ -float4 PSMain(PSInput input) : SV_TARGET - { - float3 diffuse =saturate(-dot(light_direction.xyz,input.normal.xyz))*light_color.rgb*light_color.a; - float3 ambient =ambient_color.rgb *ambient_color.a; - float3 light =(diffuse+ambient)*diffuse_color.rgb*diffuse_color.a+emission_color.rgb*emission_color.a; - float4 specular=float4(light_color.rgb*specular_color.rgb,pow(saturate(dot(reflect(normalize(light_direction.xyz),input.normal.xyz),normalize(input.camera.xyz))),specular_power)*light_color.a*specular_color.a); - float4 clr=input.color; - //--- use texture if it exist - uint width,height; - diffuse_tex.GetDimensions(width,height); - if(width*height>0) - clr*=diffuse_tex.Sample(diffuse_samp,frac(input.tcoord)); - //--- combine light with colors - return(lerp(float4(light*clr.rgb,clr.a),float4(specular.rgb,1.0),specular.a)); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/DX/Shaders/DefaultShaderVertex.hlsl b/Include/Canvas/DX/Shaders/DefaultShaderVertex.hlsl deleted file mode 100644 index 14cae19..0000000 --- a/Include/Canvas/DX/Shaders/DefaultShaderVertex.hlsl +++ /dev/null @@ -1,72 +0,0 @@ -//+------------------------------------------------------------------+ -//| Default Vertex Shader | -//| Copyright 2019, MetaQuotes Software Corp. | -//| https://www.mql5.com | -//+------------------------------------------------------------------+ - -//+------------------------------------------------------------------+ -//| Inputs for whole scene | -//+------------------------------------------------------------------+ -cbuffer InputScene : register(b0) - { - matrix view; - matrix projection; - float4 light_direction; - float4 light_color; - float4 ambient_color; - }; -//+------------------------------------------------------------------+ -//| Inputs for single object | -//+------------------------------------------------------------------+ -cbuffer InputObject : register(b1) - { - matrix transform; - float4 diffuse_color; - float4 emission_color; - float4 specular_color; - float specular_power; - float dummy[3]; - }; -//+------------------------------------------------------------------+ -//| Vertex shader input type | -//+------------------------------------------------------------------+ -struct VSInput - { - float4 position : POSITION; - float4 normal : NORMAL; - float2 tcoord : TEXCOORD; - float4 color : COLOR; - }; -//+------------------------------------------------------------------+ -//| Pixel shader input type | -//+------------------------------------------------------------------+ -struct PSInput - { - float4 position : SV_POSITION; - float4 camera : CAMERA; - float4 normal : NORMAL; - float2 tcoord : TEXCOORD; - float4 color : COLOR; - }; -//+------------------------------------------------------------------+ -//| Vertex shader entry point | -//+------------------------------------------------------------------+ -PSInput VSMain(VSInput input) - { - PSInput output; - //--- posiiton and camera direction - output.position=mul(input .position,transform); - output.position=mul(output.position,view); - output.camera =-output.position; - output.position=mul(output.position,projection); - //--- transform normals - output.normal = mul(input.normal, transform); - output.normal = mul(output.normal, view); - output.normal = normalize(output.normal); - //--- color and texture coordinates - output.tcoord =input.tcoord; - output.color =input.color; -//--- - return(output); - } -//+------------------------------------------------------------------+ diff --git a/Include/Canvas/FlameCanvas.mqh b/Include/Canvas/FlameCanvas.mqh deleted file mode 100644 index 543133b..0000000 --- a/Include/Canvas/FlameCanvas.mqh +++ /dev/null @@ -1,751 +0,0 @@ -//+------------------------------------------------------------------+ -//| FlameCanvas.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "Canvas.mqh" -#include -//+------------------------------------------------------------------+ -//| Gradient descriptors | -//+------------------------------------------------------------------+ -struct GRADIENT_COLOR - { - uint clr; // color in ARGB format - uint pos; // position of color in percentage of gradient range - }; -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -struct GRADIENT_SIZE - { - uint size; // width of gradient fill in percentage of base fill - uint pos; // position of color in percentage of gradient length - }; -//+------------------------------------------------------------------+ -//| Class CFlameCanvas | -//| Usage: generates flame | -//+------------------------------------------------------------------+ -class CFlameCanvas : public CCanvas - { -private: - //--- parameters - uint m_bar_gap; - uint m_bar_width; - uint m_chart_scale; - double m_chart_price_min; - double m_chart_price_max; - ENUM_TIMEFRAMES m_timeframe; - string m_symbol; - int m_future_bars; - int m_back_bars; - int m_rates_total; - uint m_palette[256]; // flame palette - uchar m_flame[]; // buffer for calculation of flame - uint m_time_redraw; - uint m_delay; - // bool m_resize_flag; - // int m_tick_cnt; - //--- flame parameters - datetime m_tb1; - double m_pb1; - datetime m_te1; - double m_pe1; - datetime m_tb2; - double m_pb2; - datetime m_te2; - double m_pe2; - //--- equation parameters for flame - int m_cloud_axis[100]; - double m_a1; - double m_b1; - double m_a2; - double m_b2; - int m_xb1; - int m_yb1; - int m_xe1; - int m_ye1; - int m_xb2; - int m_yb2; - int m_xe2; - int m_ye2; - -public: - CFlameCanvas(void); - ~CFlameCanvas(void); - //--- create - bool FlameCreate(const string name,const datetime time,const int future_bars,const int back_bars=0); - void RatesTotal(const int value); - //--- setting - void PaletteSet(uint clr=0xFF0000); - //--- draw - void FlameDraw(const double &prices[],const int width,const int lenght); - void FlameSet(datetime xb1,double yb1,datetime xe1,double ye1,datetime xb2,double yb2,datetime xe2,double ye2); - //--- event handler - void ChartEventHandler(const int id,const long &lparam,const double &dparam,const string &sparam); - -protected: - bool Resize(void); - void ChartScale(void); - void FlameSet(void); - void CloudDraw(const double &prices[],const int width,const int lenght,GRADIENT_SIZE &size[],GRADIENT_COLOR &gradient[],const uchar t_level=255,const bool custom_gradient=true); - void FlameDraw(const int width,const int lenght,GRADIENT_SIZE &size[],GRADIENT_COLOR &gradient[]); - void GradientVertical(const int xb,const int xe,const int yb1,const int ye1,const int yb2,const int ye2,const GRADIENT_COLOR &gradient[]); - void GradientVerticalLine(int x,int y1,int y2,const GRADIENT_COLOR &gradient[]); - void GradientVerticalLineMonochrome(int x,int y1,int y2,uint clr1,uint clr2); - void FlameCreate(void); - void FlameCalculate(void); - void Delay(const uint value); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CFlameCanvas::CFlameCanvas(void) : m_bar_gap(16), - m_bar_width(8), - m_chart_scale(1), - m_chart_price_min(0.0), - m_chart_price_max(0.0), - m_timeframe(PERIOD_CURRENT), - m_symbol(NULL), - m_future_bars(0), - m_back_bars(0), - m_rates_total(0), - m_time_redraw(0), - m_delay(50), - m_tb1(0), - m_pb1(0), - m_te1(0), - m_pe1(0), - m_tb2(0), - m_pb2(0), - m_te2(0), - m_pe2(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CFlameCanvas::~CFlameCanvas(void) - { - Destroy(); - } -//+------------------------------------------------------------------+ -//| Creates dynamic resource with object | -//+------------------------------------------------------------------+ -bool CFlameCanvas::FlameCreate(const string name,const datetime time,const int future_bars,const int back_bars) - { -//--- get chart parameters - ChartScale(); -//--- create - int width =(int)m_bar_gap*(future_bars+back_bars); - int height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); - if(!CreateBitmap(0,0,name,time-back_bars*PeriodSeconds(),m_chart_price_max,width,height,COLOR_FORMAT_ARGB_NORMALIZE)) - return(false); - ArrayResize(m_flame,width*height); -//--- save parameters - m_future_bars=future_bars; - m_back_bars =back_bars; -//--- settings - PaletteSet(); - m_timeframe =Period(); - m_symbol =Symbol(); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Resize | -//+------------------------------------------------------------------+ -bool CFlameCanvas::Resize(void) - { - int x,y; -//--- get limits - double min=ChartGetDouble(0,CHART_PRICE_MIN); - double max=ChartGetDouble(0,CHART_PRICE_MAX); - if(m_chart_price_max!=max) - { - //--- move object - ObjectSetDouble(0,m_objname,OBJPROP_PRICE,0,max); - } -//--- check - if(m_chart_price_min==min && m_chart_price_max==max) - return(false); - m_chart_price_min=min; - m_chart_price_max=max; -//--- grt size - ChartTimePriceToXY(0,0,m_tb1,min,x,y); - int width =(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS)-x; - int height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS); -//--- resize - if(width80) g+=dg; - if(i>160) b+=db; - } - } -//+------------------------------------------------------------------+ -//| Draws the flame | -//+------------------------------------------------------------------+ -void CFlameCanvas::FlameDraw(const double &prices[],const int width,const int lenght) - { - static GRADIENT_SIZE sword[]={{100,0},{150,70},{0,100}}; - static GRADIENT_COLOR flame[]={{0x00,0},{0x7F7F7F,12},{0xCCCCCC,30},{0xFFFFFF,45},{0xFFFFFF,55},{0xCCCCCC,70},{0x7F7F7F,88},{0x00,100}}; -//--- draw - CloudDraw(prices,width,lenght,sword,flame); -//--- copy flame buffer - FlameCalculate(); -//--- start timer - EventChartCustom(CONTROLS_SELF_MESSAGE,1302,0,0,NULL); - } -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -void CFlameCanvas::FlameDraw(const int width,const int lenght,GRADIENT_SIZE &size[],GRADIENT_COLOR &gradient[]) - { -//--- check - int total=ArraySize(m_cloud_axis); - if(total<2) - return; - if(total>lenght) - total=lenght; -//--- draw - int xb,xe; // coordinates of the segment - int ybm,yem; // coordinates of the center line - int yb1,ye1; // coordinates of the first line - int yb2,ye2; // coordinates of the second line -//--- for implementation of variable width - int w_total=ArraySize(size); - if(w_total<2) - return; - int w_i =0; - int w_is=(int)size[w_i].pos*total/100; - int w_ie=(int)size[w_i+1].pos*total/100; - double w =size[w_i].size*width/100; - double dw =(size[w_i+1].size*width/100-w)/(w_ie-w_is); -//--- draw from left to right - xb=0; - ybm=m_cloud_axis[0]; - yb1=ybm-(int)(w/2); - yb2=ybm+(int)(w/2); -//--- draw - for(int i=1;i=m_width) - break; - yb1=ye1; - yb2=ye2; - while(i>=w_ie-1 && i!=total-1) - { - w_i++; - w_is=(int)size[w_i].pos*total/100; - w_ie=(int)size[w_i+1].pos*total/100; - w =size[w_i].size*width/100; - if(w_ie==w_is) - { - //--- for "instant" resize - dw=size[w_i+1].size*width/100-w; - w+=dw; - ye1=yem-(int)(w/2); - ye2=yem+(int)(w/2); - //--- draw the segment of 'cloud' - GradientVertical(xb,xe,yb1,ye1,yb2,ye2,gradient); - yb1=ye1; - yb2=ye2; - } - else - { - dw=(size[w_i+1].size*width/100-w)/(w_ie-w_is); - break; - } - } - } -//--- copy flame buffer - FlameCalculate(); - } -//+------------------------------------------------------------------+ -//| Sets parameters of the flame and starts to draw | -//+------------------------------------------------------------------+ -void CFlameCanvas::FlameSet(void) - { - m_a1=m_bar_gap*((m_ye1-m_yb1)/((double)m_xe1-m_xb1)); - m_a2=m_bar_gap*((m_ye2-m_yb2)/((double)m_xe2-m_xb2)); - } -//+------------------------------------------------------------------+ -//| Sets parameters of the flame and starts to draw | -//+------------------------------------------------------------------+ -void CFlameCanvas::FlameSet(datetime tb1,double pb1, - datetime te1,double pe1, - datetime tb2,double pb2, - datetime te2,double pe2) - { - datetime obj_time =(datetime)ObjectGetInteger(0,m_objname,OBJPROP_TIME); - double obj_price=ObjectGetDouble(0,m_objname,OBJPROP_PRICE); - int dx,dy; -//--- save parameters - m_tb1=tb1; - m_pb1=pb1; - m_te1=te1; - m_pe1=pe1; - m_tb2=tb2; - m_pb2=pb2; - m_te2=te2; - m_pe2=pe2; -//--- resize - Resize(); -//--- convert - if(ChartTimePriceToXY(0,0,obj_time,obj_price,dx,dy)) - { - dy=m_yb1; - if(ChartTimePriceToXY(0,0,tb1,pb1,m_xb1,m_yb1)) - if(ChartTimePriceToXY(0,0,te1,pe1,m_xe1,m_ye1)) - if(ChartTimePriceToXY(0,0,tb2,pb2,m_xb2,m_yb2)) - if(ChartTimePriceToXY(0,0,te2,pe2,m_xe2,m_ye2)) - { - //--- convert to canvas coordinates - m_xb1-=dx; - m_xe1-=dx; - m_xb2-=dx; - m_xe2-=dx; - //--- - FlameSet(); - } - } -//--- start timer - EventChartCustom(CONTROLS_SELF_MESSAGE,1302,0,0,NULL); - } -//+------------------------------------------------------------------+ -//| Generate array that describes the body of flame | -//+------------------------------------------------------------------+ -void CFlameCanvas::FlameCreate(void) - { - static GRADIENT_SIZE sword[]={{100,0},{150,70},{0,100}}; - static GRADIENT_COLOR flame[]={{0x00,0},{0x7F7F7F,12},{0xCCCCCC,30},{0xFFFFFF,45},{0xFFFFFF,55},{0xCCCCCC,70},{0x7F7F7F,88},{0x00,100}}; -//--- - double a=rand(); // parameter of line a*x+b - double b=rand(); // parameter of line a*x+b - double c=rand(); // parameter of sine c*Sin(d*x) - double d=rand(); // parameter of sine c*Sin(d*x) - int w=rand(); // width at the base - int l=rand(); // length -//--- normalize - a=fmod(a,(m_a2-m_a1))+m_a1; - b=(m_yb1+m_yb2)/2; - c=fmod(c,20); - d=fmod(d,3*M_PI)+M_PI; -//--- shape - w%=150; - if(w<10) - w=10; // but no less than 10 - sword[1].size=w; - w=rand(); - l%=50; - sword[1].pos=l+30; - l=rand(); -//--- sizes - w=(m_yb2-m_yb1!=0) ? w%(m_yb2-m_yb1) : 10; // proportional to the starting width - if(w<10) - w=10; // but no less than 10 - l=l%((m_xe1-m_xb1)/(int)m_bar_gap-20)+20; // proportional to length -//--- create - int total=ArraySize(m_cloud_axis); - for(int i=0;ilenght) - total=lenght; -//--- draw - int xb,xe; // coordinates of the segment - int ybm,yem; // coordinates of the center line - int yb1,ye1; // coordinates of the first line - int yb2,ye2; // coordinates of the second line - int xx; -//--- for implementation of variable width - int w_total=ArraySize(size); - if(w_total<2) - return; - int w_i =0; - int w_is=(int)size[w_i].pos*total/100; - int w_ie=(int)size[w_i+1].pos*total/100; - double w =size[w_i].size*width/100; - double dw =(size[w_i+1].size*width/100-w)/(w_ie-w_is); -//--- draw from left to right - xb=0; - ChartTimePriceToXY(0,0,0,prices[0],xx,ybm); - yb1=ybm-(int)(w/2); - yb2=ybm+(int)(w/2); -//--- draw - for(int i=1;i=m_width) - break; - yb1=ye1; - yb2=ye2; - while(i>=w_ie-1 && i!=total-1) - { - w_i++; - w_is=(int)size[w_i].pos*total/100; - w_ie=(int)size[w_i+1].pos*total/100; - w =size[w_i].size*width/100; - if(w_ie==w_is) - { - //--- for "instant" resize - dw=size[w_i+1].size*width/100-w; - w+=dw; - ye1=yem-(int)(w/2); - ye2=yem+(int)(w/2); - //--- draw the segment of 'cloud' - GradientVertical(xb,xe,yb1,ye1,yb2,ye2,gradient); - yb1=ye1; - yb2=ye2; - } - else - { - dw=(size[w_i+1].size*width/100-w)/(w_ie-w_is); - break; - } - } - } - } -//+------------------------------------------------------------------+ -//| Draws area with vertical fill using specified gradient | -//+------------------------------------------------------------------+ -void CFlameCanvas::GradientVertical(const int xb,const int xe,const int yb1,const int ye1,const int yb2,const int ye2,const GRADIENT_COLOR &gradient[]) - { -//--- it is assumed that the colors array has sufficient size and positions are already sorted in ascending order -//--- get length by X and Y - int x1 =xb; - int y1 =yb1; - int x2 =xb; - int y2 =yb2; - int dx =(xe>xb)? xe-xb : xb-xe; - int dy1=(ye1>yb1)? ye1-yb1 : yb1-ye1; - int dy2=(ye2>yb2)? ye2-yb2 : yb2-ye2; -//--- get direction by X and Y - int sx =(xb-dy1) - { - //--- try to change X coordinate of the first line - //--- draw the second line - while(x2!=xe || y2!=ye2) - { - //--- calculate coordinates of next pixel of the second line - if((er2<<1)>-dy2) - { - //--- try to change X coordinate of the second line - //--- gradient fill - GradientVerticalLine(x1,y1,y2,gradient); - er2-=dy2; - if(x2!=xe) - x2+=sx; - } - if((er2<<1)0) - { - dd=dy; - dy=1; - } - else - { - dd=-dy; - dy=-1; - } -//--- increments for the color components - dc=(double)((uchar)clr2-clr)/dd; -//--- draw - for(int i=0;y1!=y2;i++,y1+=dy) - { - int idx=y1*m_width+x; - //--- check range - if(idx<0 || idx>=ArraySize(m_flame)) - continue; - if(x>=0 && x=0 && y1m_time_redraw) - { - //--- add the body of flame - FlameCreate(); - //--- draw frame - FlameCalculate(); - Update(); - //--- calculate time for the next frame - m_time_redraw=GetTickCount()+m_delay; - } - //--- generate next event for custom timer - EventChartCustom(CONTROLS_SELF_MESSAGE,1302,0,0,NULL); - break; - } - } -//+------------------------------------------------------------------+ -//| Delay | -//+------------------------------------------------------------------+ -void CFlameCanvas::Delay(const uint value) - { -//--- too small - if(value<10) - return; -//--- start delay - uint cnt=GetTickCount()+value; -//--- delay - while(cnt>=GetTickCount()); - } -//+------------------------------------------------------------------+ diff --git a/Include/ChartObjects/ChartObject.mqh b/Include/ChartObjects/ChartObject.mqh deleted file mode 100644 index 9e1566e..0000000 --- a/Include/ChartObjects/ChartObject.mqh +++ /dev/null @@ -1,1000 +0,0 @@ -//+------------------------------------------------------------------+ -//| ChartObject.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include -//+------------------------------------------------------------------+ -//| Class CChartObject. | -//| Pupose: Base class of chart objects. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CChartObject : public CObject - { -protected: - long m_chart_id; // identifier of chart the object belongs to - int m_window; // number of subwindow (0 - main window) - string m_name; // unique name object name - int m_num_points; // number of anchor points of object - -public: - CChartObject(void); - ~CChartObject(void); - //--- method of identifying the object - virtual int Type(void) const { return(0x8888); } - //--- methods of access to protected data - long ChartId(void) const { return(m_chart_id); } - int Window(void) const { return(m_window); } - string Name(void) const { return(m_name); } - bool Name(const string name); - int NumPoints(void) const { return(m_num_points); } - //--- methods of filling the object - bool Attach(long chart_id,const string name,const int window,const int points); - bool SetPoint(const int point,const datetime time,const double price) const; - //--- methods of deleting - bool Delete(void); - void Detach(void); - //--- methods of access to properties of the object - datetime Time(const int point) const; - bool Time(const int point,const datetime time) const; - double Price(const int point) const; - bool Price(const int point,const double price) const; - color Color(void) const; - bool Color(const color new_color) const; - ENUM_LINE_STYLE Style(void) const; - bool Style(const ENUM_LINE_STYLE new_style) const; - int Width(void) const; - bool Width(const int new_width) const; - bool Background(void) const; - bool Background(const bool new_back) const; - bool Fill(void) const; - bool Fill(const bool new_fill) const; - long Z_Order(void) const; - bool Z_Order(const long value) const; - bool Selected(void) const; - bool Selected(const bool new_sel) const; - bool Selectable(void) const; - bool Selectable(const bool new_sel) const; - string Description(void) const; - bool Description(const string new_text) const; - string Tooltip(void) const; - bool Tooltip(const string new_text) const; - int Timeframes(void) const; - virtual bool Timeframes(const int timeframes) const; - datetime CreateTime(void) const; - int LevelsCount(void) const; - bool LevelsCount(const int new_count) const; - //--- methods to access the properties of levels of objects - color LevelColor(const int level) const; - bool LevelColor(const int level,const color new_color) const; - ENUM_LINE_STYLE LevelStyle(const int level) const; - bool LevelStyle(const int level,const ENUM_LINE_STYLE new_style) const; - int LevelWidth(const int level) const; - bool LevelWidth(const int level,const int new_width) const; - double LevelValue(const int level) const; - bool LevelValue(const int level,const double new_value) const; - string LevelDescription(const int level) const; - bool LevelDescription(const int level,const string new_text) const; - //--- access methods to the API functions of MQL5 - long GetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier=-1) const; - bool GetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier,long &value) const; - bool SetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier,const long value) const; - bool SetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const long value) const; - double GetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier=-1) const; - bool GetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier,double &value) const; - bool SetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier,const double value) const; - bool SetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const double value) const; - string GetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier=-1) const; - bool GetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier,string &value) const; - bool SetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier,const string value) const; - bool SetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const string value) const; - //--- methods of moving - bool ShiftObject(const datetime d_time,const double d_price) const; - bool ShiftPoint(const int point,const datetime d_time,const double d_price) const; - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CChartObject::CChartObject(void) - { -//--- initialize protected data - Detach(); - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CChartObject::~CChartObject(void) - { - if(m_chart_id!=-1) - ObjectDelete(m_chart_id,m_name); - } -//+------------------------------------------------------------------+ -//| Changing name of the object | -//+------------------------------------------------------------------+ -bool CChartObject::Name(const string name) - { -//--- check - if(m_chart_id==-1) - return(false); -//--- change - if(ObjectSetString(m_chart_id,m_name,OBJPROP_NAME,name)) - { - m_name=name; - return(true); - } -//--- failure - return(false); - }; -//+------------------------------------------------------------------+ -//| Attach object | -//+------------------------------------------------------------------+ -bool CChartObject::Attach(long chart_id,const string name,const int window,const int points) - { -//--- check - if(ObjectFind(chart_id,name)<0) - return(false); -//--- attach - if(chart_id==0) - chart_id=ChartID(); - m_chart_id =chart_id; - m_window =window; - m_name =name; - m_num_points=points; -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Setting new coordinates of anchor point of an object | -//+------------------------------------------------------------------+ -bool CChartObject::SetPoint(const int point,const datetime time,const double price) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(point>=m_num_points) - return(false); -//--- result - return(ObjectMove(m_chart_id,m_name,point,time,price)); - } -//+------------------------------------------------------------------+ -//| Delete an object | -//+------------------------------------------------------------------+ -bool CChartObject::Delete(void) - { -//--- checki - if(m_chart_id==-1) - return(false); -//--- actions - bool result=ObjectDelete(m_chart_id,m_name); - Detach(); -//--- result - return(result); - } -//+------------------------------------------------------------------+ -//| Detach object | -//+------------------------------------------------------------------+ -void CChartObject::Detach(void) - { - m_chart_id =-1; - m_window =-1; - m_name =NULL; - m_num_points=0; - } -//+------------------------------------------------------------------+ -//| Get the time coordinate of the specified anchor point of object | -//+------------------------------------------------------------------+ -datetime CChartObject::Time(const int point) const - { -//--- check - if(m_chart_id==-1) - return(0); - if(point>=m_num_points) - return(0); -//--- result - return((datetime)ObjectGetInteger(m_chart_id,m_name,OBJPROP_TIME,point)); - } -//+------------------------------------------------------------------+ -//| Set the time coordinate of the specified anchor point of object | -//+------------------------------------------------------------------+ -bool CChartObject::Time(const int point,const datetime time) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(point>=m_num_points) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_TIME,point,time)); - } -//+------------------------------------------------------------------+ -//| Get the price coordinate of the specified anchor point of object.| -//+------------------------------------------------------------------+ -double CChartObject::Price(const int point) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); - if(point>=m_num_points) - return(EMPTY_VALUE); -//--- result - return(ObjectGetDouble(m_chart_id,m_name,OBJPROP_PRICE,point)); - } -//+------------------------------------------------------------------+ -//| Set the price coordinate of the specified anchor point of object.| -//+------------------------------------------------------------------+ -bool CChartObject::Price(const int point,const double price) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(point>=m_num_points) - return(false); -//--- result - return(ObjectSetDouble(m_chart_id,m_name,OBJPROP_PRICE,point,price)); - } -//+------------------------------------------------------------------+ -//| Get object color | -//+------------------------------------------------------------------+ -color CChartObject::Color(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ObjectGetInteger(m_chart_id,m_name,OBJPROP_COLOR)); - } -//+------------------------------------------------------------------+ -//| Set object color | -//+------------------------------------------------------------------+ -bool CChartObject::Color(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_COLOR,new_color)); - } -//+------------------------------------------------------------------+ -//| Get style of line of object | -//+------------------------------------------------------------------+ -ENUM_LINE_STYLE CChartObject::Style(void) const - { -//--- check - if(m_chart_id==-1) - return(WRONG_VALUE); -//--- result - return((ENUM_LINE_STYLE)ObjectGetInteger(m_chart_id,m_name,OBJPROP_STYLE)); - } -//+------------------------------------------------------------------+ -//| Set style of line of object | -//+------------------------------------------------------------------+ -bool CChartObject::Style(const ENUM_LINE_STYLE new_style) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_STYLE,new_style)); - } -//+------------------------------------------------------------------+ -//| Get width of line of object | -//+------------------------------------------------------------------+ -int CChartObject::Width(void) const - { -//--- check - if(m_chart_id==-1) - return(-1); -//--- result - return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_WIDTH)); - } -//+------------------------------------------------------------------+ -//| Set width of line of object | -//+------------------------------------------------------------------+ -bool CChartObject::Width(const int new_width) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_WIDTH,new_width)); - } -//+------------------------------------------------------------------+ -//| Get the "Draw object as background" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Background(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_BACK)); - } -//+------------------------------------------------------------------+ -//| Set the "Draw object as background" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Background(const bool new_back) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_BACK,new_back)); - } -//+------------------------------------------------------------------+ -//| Get the "Filling" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Fill(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_FILL)); - } -//+------------------------------------------------------------------+ -//| Set the "Filling" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Fill(const bool new_fill) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_FILL,new_fill)); - } -//+------------------------------------------------------------------+ -//| Get the "Z-order" property | -//+------------------------------------------------------------------+ -long CChartObject::Z_Order(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ObjectGetInteger(m_chart_id,m_name,OBJPROP_ZORDER)); - } -//+------------------------------------------------------------------+ -//| Set the "Z-order" property | -//+------------------------------------------------------------------+ -bool CChartObject::Z_Order(const long value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_ZORDER,value)); - } -//+------------------------------------------------------------------+ -//| Get the "selected" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Selected(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_SELECTED)); - } -//+------------------------------------------------------------------+ -//| Set the "selected" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Selected(const bool new_sel) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_SELECTED,new_sel)); - } -//+------------------------------------------------------------------+ -//| Get the "selectable" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Selectable(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ObjectGetInteger(m_chart_id,m_name,OBJPROP_SELECTABLE)); - } -//+------------------------------------------------------------------+ -//| Set flag the "selectable" flag | -//+------------------------------------------------------------------+ -bool CChartObject::Selectable(const bool new_sel) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_SELECTABLE,new_sel)); - } -//+------------------------------------------------------------------+ -//| Get comment of object | -//+------------------------------------------------------------------+ -string CChartObject::Description(void) const - { -//--- check - if(m_chart_id==-1) - return(""); -//--- result - return(ObjectGetString(m_chart_id,m_name,OBJPROP_TEXT)); - } -//+------------------------------------------------------------------+ -//| Set comment of object | -//+------------------------------------------------------------------+ -bool CChartObject::Description(const string new_text) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- tune - if(new_text=="") - return(ObjectSetString(m_chart_id,m_name,OBJPROP_TEXT," ")); -//--- result - return(ObjectSetString(m_chart_id,m_name,OBJPROP_TEXT,new_text)); - } -//+------------------------------------------------------------------+ -//| Get tooltip of object | -//+------------------------------------------------------------------+ -string CChartObject::Tooltip(void) const - { -//--- check - if(m_chart_id==-1) - return(""); -//--- result - return(ObjectGetString(m_chart_id,m_name,OBJPROP_TOOLTIP)); - } -//+------------------------------------------------------------------+ -//| Set tooltip of object | -//+------------------------------------------------------------------+ -bool CChartObject::Tooltip(const string new_text) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- tune - if(new_text=="") - return(ObjectSetString(m_chart_id,m_name,OBJPROP_TOOLTIP," ")); -//--- result - return(ObjectSetString(m_chart_id,m_name,OBJPROP_TOOLTIP,new_text)); - } -//+------------------------------------------------------------------+ -//| Get the "Timeframes" (visibility) flag | -//+------------------------------------------------------------------+ -int CChartObject::Timeframes(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_TIMEFRAMES)); - } -//+------------------------------------------------------------------+ -//| Set the "Timeframes" (visibility) flag | -//+------------------------------------------------------------------+ -bool CChartObject::Timeframes(const int timeframes) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_TIMEFRAMES,timeframes)); - } -//+------------------------------------------------------------------+ -//| Get time of object creation | -//+------------------------------------------------------------------+ -datetime CChartObject::CreateTime(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((datetime)ObjectGetInteger(m_chart_id,m_name,OBJPROP_CREATETIME)); - } -//+------------------------------------------------------------------+ -//| Get number of levels of object | -//+------------------------------------------------------------------+ -int CChartObject::LevelsCount(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_LEVELS)); - } -//+------------------------------------------------------------------+ -//| Set number of levels of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelsCount(const int new_count) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_LEVELS,new_count)); - } -//+------------------------------------------------------------------+ -//| Get color of the specified level of object | -//+------------------------------------------------------------------+ -color CChartObject::LevelColor(const int level) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); - if(level>=LevelsCount()) - return(CLR_NONE); -//--- result - return((color)ObjectGetInteger(m_chart_id,m_name,OBJPROP_LEVELCOLOR,level)); - } -//+------------------------------------------------------------------+ -//| Set color of the specified level of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelColor(const int level,const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(level>=LevelsCount()) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_LEVELCOLOR,level,new_color)); - } -//+------------------------------------------------------------------+ -//| Get line style of the specified level of object | -//+------------------------------------------------------------------+ -ENUM_LINE_STYLE CChartObject::LevelStyle(const int level) const - { -//--- check - if(m_chart_id==-1) - return(WRONG_VALUE); - if(level>=LevelsCount()) - return(WRONG_VALUE); -//--- result - return((ENUM_LINE_STYLE)ObjectGetInteger(m_chart_id,m_name,OBJPROP_LEVELSTYLE,level)); - } -//+------------------------------------------------------------------+ -//| Set line style of the specified level of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelStyle(const int level,const ENUM_LINE_STYLE new_style) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(level>=LevelsCount()) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_LEVELSTYLE,level,new_style)); - } -//+------------------------------------------------------------------+ -//| Get line width of the specified level of object | -//+------------------------------------------------------------------+ -int CChartObject::LevelWidth(const int level) const - { -//--- check - if(m_chart_id==-1) - return(-1); - if(level>=LevelsCount()) - return(-1); -//--- result - return((int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_LEVELWIDTH,level)); - } -//+------------------------------------------------------------------+ -//| Set line width of the specified level of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelWidth(const int level,const int new_width) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(level>=LevelsCount()) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,OBJPROP_LEVELWIDTH,level,new_width)); - } -//+------------------------------------------------------------------+ -//| Get value of the specified level of object | -//+------------------------------------------------------------------+ -double CChartObject::LevelValue(const int level) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); - if(level>=LevelsCount()) - return(EMPTY_VALUE); -//--- result - return(ObjectGetDouble(m_chart_id,m_name,OBJPROP_LEVELVALUE,level)); - } -//+------------------------------------------------------------------+ -//| Set value of the specified level of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelValue(const int level,const double new_value) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(level>=LevelsCount()) - return(false); -//--- result - return(ObjectSetDouble(m_chart_id,m_name,OBJPROP_LEVELVALUE,level,new_value)); - } -//+------------------------------------------------------------------+ -//| Get comment of of the specified level of object | -//+------------------------------------------------------------------+ -string CChartObject::LevelDescription(const int level) const - { -//--- check - if(m_chart_id==-1) - return(""); - if(level>=LevelsCount()) - return(""); -//--- result - return(ObjectGetString(m_chart_id,m_name,OBJPROP_LEVELTEXT,level)); - } -//+------------------------------------------------------------------+ -//| Set comment to the specified level of object | -//+------------------------------------------------------------------+ -bool CChartObject::LevelDescription(const int level,const string new_text) const - { -//--- checking - if(m_chart_id==-1) - return(false); - if(level>=LevelsCount()) - return(false); -//--- result - return(ObjectSetString(m_chart_id,m_name,OBJPROP_LEVELTEXT,level,new_text)); - } -//+------------------------------------------------------------------+ -//| Access function long ObjectGetInteger(...) | -//+------------------------------------------------------------------+ -long CChartObject::GetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- - if(modifier==-1) - return(ObjectGetInteger(m_chart_id,m_name,prop_id)); -//--- result - return(ObjectGetInteger(m_chart_id,m_name,prop_id,modifier)); - } -//+------------------------------------------------------------------+ -//| Access function bool ObjectGetInteger(...) | -//+------------------------------------------------------------------+ -bool CChartObject::GetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier,long &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectGetInteger(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetInteger(.,modifier,.) | -//+------------------------------------------------------------------+ -bool CChartObject::SetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const int modifier,const long value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetInteger(...) | -//+------------------------------------------------------------------+ -bool CChartObject::SetInteger(const ENUM_OBJECT_PROPERTY_INTEGER prop_id,const long value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetInteger(m_chart_id,m_name,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function double ObjectGetDouble(...) | -//+------------------------------------------------------------------+ -double CChartObject::GetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- - if(modifier==-1) - return(ObjectGetDouble(m_chart_id,m_name,prop_id)); -//--- result - return(ObjectGetDouble(m_chart_id,m_name,prop_id,modifier)); - } -//+------------------------------------------------------------------+ -//| Access function bool ObjectGetDouble(...) | -//+------------------------------------------------------------------+ -bool CChartObject::GetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier,double &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectGetDouble(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetDouble(.,modifier,.) | -//+------------------------------------------------------------------+ -bool CChartObject::SetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const int modifier,const double value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetDouble(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetDouble(...) | -//+------------------------------------------------------------------+ -bool CChartObject::SetDouble(const ENUM_OBJECT_PROPERTY_DOUBLE prop_id,const double value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetDouble(m_chart_id,m_name,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function string ObjectGetString (...) | -//+------------------------------------------------------------------+ -string CChartObject::GetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier) const - { -//--- check - if(m_chart_id==-1) - return(""); -//--- - if(modifier==-1) - return(ObjectGetString(m_chart_id,m_name,prop_id)); -//--- result - return(ObjectGetString(m_chart_id,m_name,prop_id,modifier)); - } -//+------------------------------------------------------------------+ -//| Access function bool ObjectGetString(...) | -//+------------------------------------------------------------------+ -bool CChartObject::GetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier,string &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectGetString(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetString(.,modifier,.) | -//+------------------------------------------------------------------+ -bool CChartObject::SetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const int modifier,const string value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetString(m_chart_id,m_name,prop_id,modifier,value)); - } -//+------------------------------------------------------------------+ -//| Access function ObjectSetString(...) | -//+------------------------------------------------------------------+ -bool CChartObject::SetString(const ENUM_OBJECT_PROPERTY_STRING prop_id,const string value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ObjectSetString(m_chart_id,m_name,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Relative movement of object | -//+------------------------------------------------------------------+ -bool CChartObject::ShiftObject(const datetime d_time,const double d_price) const - { - bool result=true; - int i; -//--- check - if(m_chart_id==-1) - return(false); -//--- move - for(i=0;i=m_num_points) - return(false); -//--- move - datetime time=(datetime)ObjectGetInteger(m_chart_id,m_name,OBJPROP_TIME,point); - double price=ObjectGetDouble(m_chart_id,m_name,OBJPROP_PRICE,point); -//--- result - return(ObjectMove(m_chart_id,m_name,point,time+d_time,price+d_price)); - } -//+------------------------------------------------------------------+ -//| Writing object parameters to file | -//+------------------------------------------------------------------+ -bool CChartObject::Save(const int file_handle) - { - int i,len; - int levels; - string str; -//--- check - if(file_handle==INVALID_HANDLE || m_chart_id==-1) - return(false); -//--- write start marker - 0xFFFFFFFFFFFFFFFF - if(FileWriteLong(file_handle,-1)!=sizeof(long)) - return(false); -//--- write object type - if(FileWriteInteger(file_handle,Type(),INT_VALUE)!=INT_VALUE) - return(false); -//--- write object name - str=ObjectGetString(m_chart_id,m_name,OBJPROP_NAME); - len=StringLen(str); - if(FileWriteInteger(file_handle,len,INT_VALUE)!=INT_VALUE) - return(false); - if(len!=0) if(FileWriteString(file_handle,str,len)!=len) - return(false); -//--- write object color - if(FileWriteLong(file_handle,ObjectGetInteger(m_chart_id,m_name,OBJPROP_COLOR))!=sizeof(long)) - return(false); -//--- write object line style - if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_STYLE))!=sizeof(int)) - return(false); -//--- write object line width - if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_WIDTH))!=sizeof(int)) - return(false); -//--- write the property value "Background" - if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_BACK),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write the property value "Selectable" - if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_SELECTABLE),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write the property value "Timeframes" - if(FileWriteInteger(file_handle,(int)ObjectGetInteger(m_chart_id,m_name,OBJPROP_TIMEFRAMES),INT_VALUE)!=sizeof(int)) - return(false); -//--- write comment - str=ObjectGetString(m_chart_id,m_name,OBJPROP_TEXT); - len=StringLen(str); - if(FileWriteInteger(file_handle,len,INT_VALUE)!=INT_VALUE) - return(false); - if(len!=0) if(FileWriteString(file_handle,str,len)!=len) - return(false); -//--- write number of points - if(FileWriteInteger(file_handle,m_num_points,INT_VALUE)!=INT_VALUE) - return(false); -//--- write points - for(i=0;i -#include -#include -//+------------------------------------------------------------------+ -//| Class CChartObjectPanel. | -//| Purpose: Class for grouping objects for managing a chart | -//+------------------------------------------------------------------+ -class CChartObjectPanel : public CChartObjectButton - { -protected: - CArrayObj m_attachment; // array of attached objects - CArrayInt m_dX; // array of dX attached objects - CArrayInt m_dY; // array of dY attached objects - bool m_expanded; // collapsed/expanded flag - -public: - CChartObjectPanel(); - ~CChartObjectPanel(); - //--- method for attaching objects - bool Attach(CChartObjectLabel *chart_object); - bool X_Distance(const int X); - int X_Distance(void) const { return(CChartObjectButton::X_Distance()); } - bool Y_Distance(const int Y); - int Y_Distance(void) const { return(CChartObjectButton::Y_Distance()); } - int X_Size() const; - int X_Size(const int Y) const { return(CChartObjectButton::X_Size()); } - int Y_Size() const; - int Y_Size(const int Y) const { return(CChartObjectButton::Y_Size()); } - - int Timeframes(void) const { return(CChartObjectButton::Timeframes()); } - virtual bool Timeframes(const int timeframes); - bool State(const bool state); - bool State(void) const { return(CChartObjectButton::State()); } - bool CheckState(); - -protected: - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -void CChartObjectPanel::CChartObjectPanel(void) : m_expanded(true) - { - } -//+------------------------------------------------------------------+ -//| Destructor. | -//+------------------------------------------------------------------+ -void CChartObjectPanel::~CChartObjectPanel(void) - { -//--- All objects added by the method Add(), deleted automatically - } -//+------------------------------------------------------------------+ -//| Method Attach | -//+------------------------------------------------------------------+ -bool CChartObjectPanel::Attach(CChartObjectLabel *chart_object) - { - if(m_attachment.Add(chart_object)) - { - int x,y; - x=chart_object.X_Distance(); - m_dX.Add(chart_object.X_Distance()); - x+=X_Distance(); - chart_object.X_Distance(X_Distance()+chart_object.X_Distance()); - y=CChartObjectButton::Y_Size(); - y+=chart_object.Y_Distance(); - m_dY.Add(chart_object.Y_Distance()+CChartObjectButton::Y_Size()+2); - chart_object.Y_Distance(Y_Distance()+chart_object.Y_Distance()+CChartObjectButton::Y_Size()+2); - return(true); - } -//--- - return(false); - } -//+------------------------------------------------------------------+ -//| Method X_Distance | -//+------------------------------------------------------------------+ -bool CChartObjectPanel::X_Distance(const int X) - { - CChartObjectLabel *chart_object; -//--- - for(int i=0;i -//+------------------------------------------------------------------+ -//| Class CChart. | -//| Purpose: Class of the "Chart" object. | -//| Derives from class CObject. | -//+------------------------------------------------------------------+ -class CChart : public CObject - { -protected: - long m_chart_id; // chart identifier -public: - CChart(void); - ~CChart(void); - //--- methods of access to protected data - long ChartId(void) const { return(m_chart_id); } - //--- method of identifying the object - virtual int Type(void) const { return(0x1111); } - //--- methods of access to properties of the chart - //--- common properties - ENUM_CHART_MODE Mode(void) const; - bool Mode(const ENUM_CHART_MODE mode) const; - bool Foreground(void) const; - bool Foreground(const bool foreground) const; - bool Shift(void) const; - bool Shift(const bool shift) const; - double ShiftSize(void) const; - bool ShiftSize(double shift) const; - bool AutoScroll(void) const; - bool AutoScroll(const bool auto_scroll) const; - int Scale(void) const; - bool Scale(int scale) const; - bool ScaleFix(void) const; - bool ScaleFix(const bool scale_fix) const; - bool ScaleFix_11(void) const; - bool ScaleFix_11(const bool scale_fix_11) const; - double FixedMax(void) const; - bool FixedMax(const double fixed_max) const; - double FixedMin(void) const; - bool FixedMin(const double fixed_min) const; - bool ScalePPB(void) const; - bool ScalePPB(const bool scale_ppb) const; - double PointsPerBar(void) const; - bool PointsPerBar(const double points_per_bar) const; - //--- show properties - bool ShowOHLC(void) const; - bool ShowOHLC(const bool show) const; - bool ShowLineBid(void) const; - bool ShowLineBid(const bool show) const; - bool ShowLineAsk(void) const; - bool ShowLineAsk(const bool show) const; - bool ShowLastLine(void) const; - bool ShowLastLine(const bool show) const; - bool ShowPeriodSep(void) const; - bool ShowPeriodSep(const bool show) const; - bool ShowGrid(void) const; - bool ShowGrid(const bool show) const; - ENUM_CHART_VOLUME_MODE ShowVolumes(void) const; - bool ShowVolumes(const ENUM_CHART_VOLUME_MODE show) const; - bool ShowObjectDescr(void) const; - bool ShowObjectDescr(const bool show) const; - bool ShowDateScale(const bool show) const; - bool ShowPriceScale(const bool show) const; - //--- color properties - color ColorBackground(void) const; - bool ColorBackground(const color new_color) const; - color ColorForeground(void) const; - bool ColorForeground(const color new_color) const; - color ColorGrid(void) const; - bool ColorGrid(const color new_color) const; - color ColorBarUp(void) const; - bool ColorBarUp(const color new_color) const; - color ColorBarDown(void) const; - bool ColorBarDown(const color new_color) const; - color ColorCandleBull(void) const; - bool ColorCandleBull(const color new_color) const; - color ColorCandleBear(void) const; - bool ColorCandleBear(const color new_color) const; - color ColorChartLine(void) const; - bool ColorChartLine(const color new_color) const; - color ColorVolumes(void) const; - bool ColorVolumes(const color new_color) const; - color ColorLineBid(void) const; - bool ColorLineBid(const color new_color) const; - color ColorLineAsk(void) const; - bool ColorLineAsk(const color new_color) const; - color ColorLineLast(void) const; - bool ColorLineLast(const color new_color) const; - color ColorStopLevels(void) const; - bool ColorStopLevels(const color new_color) const; - //--- other properties - bool BringToTop(void) const; - bool EventObjectCreate(const bool flag=true) const; - bool EventObjectDelete(const bool flag=true) const; - bool EventMouseMove(const bool flag=true) const; - bool MouseScroll(const bool flag=true) const; - //--- methods of access to READ ONLY properties of the chart - int VisibleBars(void) const; - int WindowsTotal(void) const; - bool WindowIsVisible(const int num) const; - int WindowHandle(void) const; - int FirstVisibleBar(void) const; - int WidthInBars(void) const; - int WidthInPixels(void) const; - int HeightInPixels(const int num) const; - int SubwindowY(const int num) const; - double PriceMin(const int num) const; - double PriceMax(const int num) const; - bool IsObject(void) const; - //--- methods of binding chart - void Attach(void) { m_chart_id=ChartID(); } - void Attach(const long chart) { m_chart_id=chart; } - void FirstChart(void) { m_chart_id=ChartFirst(); } - void NextChart(void) { m_chart_id=ChartNext(m_chart_id); } - long Open(const string symbol_name,const ENUM_TIMEFRAMES timeframe); - void Detach(void) { m_chart_id=-1; } - void Close(void); - //--- navigation method - bool Navigate(const ENUM_CHART_POSITION position,const int shift=0) const; - //--- methods of access to the API functions of MQL5 - string Symbol(void) const { return(ChartSymbol(m_chart_id)); } - ENUM_TIMEFRAMES Period(void) const { return(ChartPeriod(m_chart_id)); } - void Redraw(void) const { ChartRedraw(m_chart_id); } - long GetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const int sub_window=0) const; - bool GetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const int sub_window,long &value) const; - bool SetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const long value) const; - double GetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const int sub_window=0) const; - bool GetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const int sub_window,double &value) const; - bool SetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const double value) const; - string GetString(const ENUM_CHART_PROPERTY_STRING prop_id) const; - bool GetString(const ENUM_CHART_PROPERTY_STRING prop_id,string &value) const; - bool SetString(const ENUM_CHART_PROPERTY_STRING prop_id,const string value) const; - bool SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period) const; - bool ApplyTemplate(const string filename) const; - bool ScreenShot(const string filename,const int width,const int height, - const ENUM_ALIGN_MODE align_mode=ALIGN_RIGHT) const; - int WindowOnDropped(void) const; - double PriceOnDropped(void) const; - datetime TimeOnDropped(void) const; - int XOnDropped(void) const; - int YOnDropped(void) const; - //--- methods for working with indicators - bool IndicatorAdd(const int subwin,const int handle) const; - bool IndicatorDelete(const int subwin,const string name) const; - int IndicatorsTotal(const int subwin) const; - string IndicatorName(const int subwin,const int index) const; - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CChart::CChart(void) : m_chart_id(-1) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CChart::~CChart(void) - { - if(m_chart_id!=-1) - Close(); - } -//+------------------------------------------------------------------+ -//| Opening chart | -//+------------------------------------------------------------------+ -long CChart::Open(const string symbol_name,const ENUM_TIMEFRAMES timeframe) - { - m_chart_id=ChartOpen(symbol_name,timeframe); - if(m_chart_id==0) - m_chart_id=-1; - return(m_chart_id); - } -//+------------------------------------------------------------------+ -//| Get the type of representation of chart | -//+------------------------------------------------------------------+ -ENUM_CHART_MODE CChart::Mode(void) const - { -//--- check - if(m_chart_id==-1) - return(WRONG_VALUE); -//--- result - return((ENUM_CHART_MODE)ChartGetInteger(m_chart_id,CHART_MODE)); - } -//+------------------------------------------------------------------+ -//| Set the type of representation chart | -//+------------------------------------------------------------------+ -bool CChart::Mode(const ENUM_CHART_MODE mode) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_MODE,mode)); - } -//+------------------------------------------------------------------+ -//| Get value of the "Foreground" property | -//+------------------------------------------------------------------+ -bool CChart::Foreground(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_FOREGROUND)); - } -//+------------------------------------------------------------------+ -//| Set value of the "Foreground" property | -//+------------------------------------------------------------------+ -bool CChart::Foreground(const bool foreground) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_FOREGROUND,foreground)); - } -//+------------------------------------------------------------------+ -//| Get value of the "Shift" property | -//+------------------------------------------------------------------+ -bool CChart::Shift(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHIFT)); - } -//+------------------------------------------------------------------+ -//| Set value of the "Shift"property | -//+------------------------------------------------------------------+ -bool CChart::Shift(const bool shift) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHIFT,shift)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShiftSize" property | -//+------------------------------------------------------------------+ -double CChart::ShiftSize(void) const - { -//--- check - if(m_chart_id==-1) - return(DBL_MAX); -//--- result - return(ChartGetDouble(m_chart_id,CHART_SHIFT_SIZE)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShiftSize" property | -//+------------------------------------------------------------------+ -bool CChart::ShiftSize(double shift) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(shift<10) - shift=10; - if(shift>50) - shift=50; -//--- result - return(ChartSetDouble(m_chart_id,CHART_SHIFT_SIZE,shift)); - } -//+------------------------------------------------------------------+ -//| Get value of the "AutoScroll" property | -//+------------------------------------------------------------------+ -bool CChart::AutoScroll(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_AUTOSCROLL)); - } -//+------------------------------------------------------------------+ -//| Set value of the "AutoScroll" property | -//+------------------------------------------------------------------+ -bool CChart::AutoScroll(const bool auto_scroll) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_AUTOSCROLL,auto_scroll)); - } -//+------------------------------------------------------------------+ -//| Get value of the "Scale" property | -//+------------------------------------------------------------------+ -int CChart::Scale(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_SCALE)); - } -//+------------------------------------------------------------------+ -//| Set value of the "Scale" property | -//+------------------------------------------------------------------+ -bool CChart::Scale(int shift) const - { -//--- check - if(m_chart_id==-1) - return(false); - if(shift<0) - shift=0; - if(shift>32) - shift=32; -//--- result - return(ChartSetInteger(m_chart_id,CHART_SCALE,shift)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ScaleFix" property | -//+------------------------------------------------------------------+ -bool CChart::ScaleFix(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SCALEFIX)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ScaleFix" property | -//+------------------------------------------------------------------+ -bool CChart::ScaleFix(const bool scale_fix) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SCALEFIX,scale_fix)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ScaleFix_11" property | -//+------------------------------------------------------------------+ -bool CChart::ScaleFix_11(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SCALEFIX_11)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ScaleFix_11" property | -//+------------------------------------------------------------------+ -bool CChart::ScaleFix_11(const bool scale_fix_11) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SCALEFIX_11,scale_fix_11)); - } -//+------------------------------------------------------------------+ -//| Get value of the "FixedMax" property | -//+------------------------------------------------------------------+ -double CChart::FixedMax(void) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,CHART_FIXED_MAX)); - } -//+------------------------------------------------------------------+ -//| Set value of the "FixedMax" property | -//+------------------------------------------------------------------+ -bool CChart::FixedMax(const double fixed_max) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetDouble(m_chart_id,CHART_FIXED_MAX,fixed_max)); - } -//+------------------------------------------------------------------+ -//| Get value of the "FixedMin" property | -//+------------------------------------------------------------------+ -double CChart::FixedMin(void) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,CHART_FIXED_MIN)); - } -//+------------------------------------------------------------------+ -//| Set value of the "FixedMin" property | -//+------------------------------------------------------------------+ -bool CChart::FixedMin(const double fixed_min) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetDouble(m_chart_id,CHART_FIXED_MIN,fixed_min)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ScalePointsPerBar" property | -//+------------------------------------------------------------------+ -bool CChart::ScalePPB(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SCALE_PT_PER_BAR)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ScalePointsPerBar" property | -//+------------------------------------------------------------------+ -bool CChart::ScalePPB(const bool scale_ppb) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SCALE_PT_PER_BAR,scale_ppb)); - } -//+------------------------------------------------------------------+ -//| Get value of the "PointsPerBar" property | -//+------------------------------------------------------------------+ -double CChart::PointsPerBar(void) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,CHART_POINTS_PER_BAR)); - } -//+------------------------------------------------------------------+ -//| Set value of the "PointsPerBar" property | -//+------------------------------------------------------------------+ -bool CChart::PointsPerBar(const double points_per_bar) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetDouble(m_chart_id,CHART_POINTS_PER_BAR,points_per_bar)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowOHLC" property | -//+------------------------------------------------------------------+ -bool CChart::ShowOHLC(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_OHLC)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowOHLC" property | -//+------------------------------------------------------------------+ -bool CChart::ShowOHLC(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_OHLC,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowLineBid" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLineBid(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_BID_LINE)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowLineBid" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLineBid(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_BID_LINE,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowLineAsk" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLineAsk(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_ASK_LINE)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowLineAsk" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLineAsk(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_ASK_LINE,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowLastLine" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLastLine(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_LAST_LINE)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowLastLine" property | -//+------------------------------------------------------------------+ -bool CChart::ShowLastLine(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_LAST_LINE,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowPeriodSep" property | -//+------------------------------------------------------------------+ -bool CChart::ShowPeriodSep(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_PERIOD_SEP)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowPeriodSep" property | -//+------------------------------------------------------------------+ -bool CChart::ShowPeriodSep(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_PERIOD_SEP,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowGrid" property | -//+------------------------------------------------------------------+ -bool CChart::ShowGrid(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_GRID)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowGrid" property | -//+------------------------------------------------------------------+ -bool CChart::ShowGrid(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_GRID,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowVolumes" property | -//+------------------------------------------------------------------+ -ENUM_CHART_VOLUME_MODE CChart::ShowVolumes(void) const - { -//--- check - if(m_chart_id==-1) - return(WRONG_VALUE); -//--- result - return((ENUM_CHART_VOLUME_MODE)ChartGetInteger(m_chart_id,CHART_SHOW_VOLUMES)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowVolumes" property | -//+------------------------------------------------------------------+ -bool CChart::ShowVolumes(const ENUM_CHART_VOLUME_MODE show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_VOLUMES,show)); - } -//+------------------------------------------------------------------+ -//| Get value of the "ShowObjectDescr" property | -//+------------------------------------------------------------------+ -bool CChart::ShowObjectDescr(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_SHOW_OBJECT_DESCR)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowObjectDescr" property | -//+------------------------------------------------------------------+ -bool CChart::ShowObjectDescr(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_OBJECT_DESCR,show)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowDateScale" property | -//+------------------------------------------------------------------+ -bool CChart::ShowDateScale(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_DATE_SCALE,show)); - } -//+------------------------------------------------------------------+ -//| Set value of the "ShowPriceScale" property | -//+------------------------------------------------------------------+ -bool CChart::ShowPriceScale(const bool show) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_SHOW_PRICE_SCALE,show)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Background" property | -//+------------------------------------------------------------------+ -color CChart::ColorBackground(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_BACKGROUND)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Background" property | -//+------------------------------------------------------------------+ -bool CChart::ColorBackground(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_BACKGROUND,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Foreground" property | -//+------------------------------------------------------------------+ -color CChart::ColorForeground(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_FOREGROUND)); - } -//+------------------------------------------------------------------+ -//| Set color value for the "Foreground" property | -//+------------------------------------------------------------------+ -bool CChart::ColorForeground(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_FOREGROUND,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Grid" property | -//+------------------------------------------------------------------+ -color CChart::ColorGrid(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_GRID)); - } -//+------------------------------------------------------------------+ -//| Set color value for the "Grid" property | -//+------------------------------------------------------------------+ -bool CChart::ColorGrid(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_GRID,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Bar Up" property | -//+------------------------------------------------------------------+ -color CChart::ColorBarUp(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_CHART_UP)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Bar Up" property | -//+------------------------------------------------------------------+ -bool CChart::ColorBarUp(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_CHART_UP,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Bar Down" property | -//+------------------------------------------------------------------+ -color CChart::ColorBarDown(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_CHART_DOWN)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Bar Down" property | -//+------------------------------------------------------------------+ -bool CChart::ColorBarDown(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_CHART_DOWN,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Candle Bull" property | -//+------------------------------------------------------------------+ -color CChart::ColorCandleBull(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_CANDLE_BULL)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Candle Bull" property | -//+------------------------------------------------------------------+ -bool CChart::ColorCandleBull(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_CANDLE_BULL,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Candle Bear" property | -//+------------------------------------------------------------------+ -color CChart::ColorCandleBear(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_CANDLE_BEAR)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Candle Bear" property | -//+------------------------------------------------------------------+ -bool CChart::ColorCandleBear(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_CANDLE_BEAR,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Chart Line" property | -//+------------------------------------------------------------------+ -color CChart::ColorChartLine(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_CHART_LINE)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Chart Line" property | -//+------------------------------------------------------------------+ -bool CChart::ColorChartLine(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_CHART_LINE,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Volumes" property | -//+------------------------------------------------------------------+ -color CChart::ColorVolumes(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_VOLUME)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Volumes" property | -//+------------------------------------------------------------------+ -bool CChart::ColorVolumes(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_VOLUME,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Line Bid" property | -//+------------------------------------------------------------------+ -color CChart::ColorLineBid(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_BID)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Line Bid" property | -//+------------------------------------------------------------------+ -bool CChart::ColorLineBid(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_BID,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Line Ask" property | -//+------------------------------------------------------------------+ -color CChart::ColorLineAsk(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_ASK)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Line Ask" property | -//+------------------------------------------------------------------+ -bool CChart::ColorLineAsk(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_ASK,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Line Last" property | -//+------------------------------------------------------------------+ -color CChart::ColorLineLast(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_LAST)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Line Last" property | -//+------------------------------------------------------------------+ -bool CChart::ColorLineLast(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_LAST,new_color)); - } -//+------------------------------------------------------------------+ -//| Get color value of the "Stop Levels" property | -//+------------------------------------------------------------------+ -color CChart::ColorStopLevels(void) const - { -//--- check - if(m_chart_id==-1) - return(CLR_NONE); -//--- result - return((color)ChartGetInteger(m_chart_id,CHART_COLOR_STOP_LEVEL)); - } -//+------------------------------------------------------------------+ -//| Set color value of the "Stop Levels" property | -//+------------------------------------------------------------------+ -bool CChart::ColorStopLevels(const color new_color) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_COLOR_STOP_LEVEL,new_color)); - } -//+------------------------------------------------------------------+ -//| Shows chart always on top | -//+------------------------------------------------------------------+ -bool CChart::BringToTop(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_BRING_TO_TOP,true)); - } -//+------------------------------------------------------------------+ -//| Sets flag to generate event of creating objects | -//+------------------------------------------------------------------+ -bool CChart::EventObjectCreate(const bool flag) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_EVENT_OBJECT_CREATE,flag)); - } -//+------------------------------------------------------------------+ -//| Sets flag to generate event of deleting objects | -//+------------------------------------------------------------------+ -bool CChart::EventObjectDelete(const bool flag) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_EVENT_OBJECT_DELETE,flag)); - } -//+------------------------------------------------------------------+ -//| Sets flag to generate event of moving mouse cursor | -//+------------------------------------------------------------------+ -bool CChart::EventMouseMove(const bool flag) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_EVENT_MOUSE_MOVE,flag)); - } -//+------------------------------------------------------------------+ -//| Sets flag to mouse scrolling | -//+------------------------------------------------------------------+ -bool CChart::MouseScroll(const bool flag) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetInteger(m_chart_id,CHART_MOUSE_SCROLL,flag)); - } -//+------------------------------------------------------------------+ -//| Get value of the "VisibleBars" property | -//+------------------------------------------------------------------+ -int CChart::VisibleBars(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WIDTH_IN_BARS)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WindowsTotal" property | -//+------------------------------------------------------------------+ -int CChart::WindowsTotal(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WINDOWS_TOTAL)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WindowIsVisible" property | -//+------------------------------------------------------------------+ -bool CChart::WindowIsVisible(const int num) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_WINDOW_IS_VISIBLE,num)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WindowHandle" property | -//+------------------------------------------------------------------+ -int CChart::WindowHandle(void) const - { -//--- check - if(m_chart_id==-1) - return(INVALID_HANDLE); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WINDOW_HANDLE)); - } -//+------------------------------------------------------------------+ -//| Get value of the "FirstVisibleBar" property | -//+------------------------------------------------------------------+ -int CChart::FirstVisibleBar(void) const - { -//--- check - if(m_chart_id==-1) - return(-1); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_FIRST_VISIBLE_BAR)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WidthInBars" property | -//+------------------------------------------------------------------+ -int CChart::WidthInBars(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WIDTH_IN_BARS)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WidthInPixels" property | -//+------------------------------------------------------------------+ -int CChart::WidthInPixels(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WIDTH_IN_PIXELS)); - } -//+------------------------------------------------------------------+ -//| Get value of the "HeightInPixels" property | -//+------------------------------------------------------------------+ -int CChart::HeightInPixels(const int num) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_HEIGHT_IN_PIXELS,num)); - } -//+------------------------------------------------------------------+ -//| Get value of the "WindowYDistance" property | -//+------------------------------------------------------------------+ -int CChart::SubwindowY(const int num) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return((int)ChartGetInteger(m_chart_id,CHART_WINDOW_YDISTANCE,num)); - } -//+------------------------------------------------------------------+ -//| Get value of the "PriceMin" property | -//+------------------------------------------------------------------+ -double CChart::PriceMin(const int num) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,CHART_PRICE_MIN,num)); - } -//+------------------------------------------------------------------+ -//| Get value of the "PriceMax" property | -//+------------------------------------------------------------------+ -double CChart::PriceMax(const int num) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,CHART_PRICE_MAX,num)); - } -//+------------------------------------------------------------------+ -//| Get value of the "IsObject" property | -//+------------------------------------------------------------------+ -bool CChart::IsObject(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return((bool)ChartGetInteger(m_chart_id,CHART_IS_OBJECT)); - } -//+------------------------------------------------------------------+ -//| Chart close | -//+------------------------------------------------------------------+ -void CChart::Close(void) - { - if(m_chart_id!=-1) - { - ChartClose(m_chart_id); - m_chart_id=-1; - } - } -//+------------------------------------------------------------------+ -//| Chart navigation | -//+------------------------------------------------------------------+ -bool CChart::Navigate(const ENUM_CHART_POSITION position,const int shift) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartNavigate(m_chart_id,position,shift)); - } -//+------------------------------------------------------------------+ -//| Access functions long ChartGetInteger(...) | -//+------------------------------------------------------------------+ -long CChart::GetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const int subwindow) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ChartGetInteger(m_chart_id,prop_id,subwindow)); - } -//+------------------------------------------------------------------+ -//| Access function bool ChartGetInteger(...) | -//+------------------------------------------------------------------+ -bool CChart::GetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const int subwindow,long &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartGetInteger(m_chart_id,prop_id,subwindow,value)); - } -//+------------------------------------------------------------------+ -//| Access function ChartSetInteger(...) | -//+------------------------------------------------------------------+ -bool CChart::SetInteger(const ENUM_CHART_PROPERTY_INTEGER prop_id,const long value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- - return(ChartSetInteger(m_chart_id,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function double ChartGetDouble(...) | -//+------------------------------------------------------------------+ -double CChart::GetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const int subwindow) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartGetDouble(m_chart_id,prop_id,subwindow)); - } -//+------------------------------------------------------------------+ -//| Access function bool ChartGetDouble(...) | -//+------------------------------------------------------------------+ -bool CChart::GetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const int subwindow,double &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartGetDouble(m_chart_id,prop_id,subwindow,value)); - } -//+------------------------------------------------------------------+ -//| Access function ChartSetDouble(...) | -//+------------------------------------------------------------------+ -bool CChart::SetDouble(const ENUM_CHART_PROPERTY_DOUBLE prop_id,const double value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetDouble(m_chart_id,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function string ChartGetString(...) | -//+------------------------------------------------------------------+ -string CChart::GetString(const ENUM_CHART_PROPERTY_STRING prop_id) const - { -//--- check - if(m_chart_id==-1) - return(""); -//--- result - return(ChartGetString(m_chart_id,prop_id)); - } -//+------------------------------------------------------------------+ -//| Access functions bool ChartGetString(...) | -//+------------------------------------------------------------------+ -bool CChart::GetString(const ENUM_CHART_PROPERTY_STRING prop_id,string &value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartGetString(m_chart_id,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function ChartSetString(...) | -//+------------------------------------------------------------------+ -bool CChart::SetString(const ENUM_CHART_PROPERTY_STRING prop_id,const string value) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetString(m_chart_id,prop_id,value)); - } -//+------------------------------------------------------------------+ -//| Access function ChartSetSymbolPeriod(...) | -//+------------------------------------------------------------------+ -bool CChart::SetSymbolPeriod(const string symbol,const ENUM_TIMEFRAMES period) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartSetSymbolPeriod(m_chart_id,symbol,period)); - } -//+------------------------------------------------------------------+ -//| Access function ChartApplyTemplate(...) | -//+------------------------------------------------------------------+ -bool CChart::ApplyTemplate(const string filename) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartApplyTemplate(m_chart_id,filename)); - } -//+------------------------------------------------------------------+ -//| Access function ChartScreenShot(...) | -//+------------------------------------------------------------------+ -bool CChart::ScreenShot(const string filename,const int width,const int height,const ENUM_ALIGN_MODE align_mode) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartScreenShot(m_chart_id,filename,width,height,align_mode)); - } -//+------------------------------------------------------------------+ -//| Access function WindowOnDropped() | -//+------------------------------------------------------------------+ -int CChart::WindowOnDropped(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ChartWindowOnDropped()); - } -//+------------------------------------------------------------------+ -//| Access function PriceOnDropped() | -//+------------------------------------------------------------------+ -double CChart::PriceOnDropped(void) const - { -//--- check - if(m_chart_id==-1) - return(EMPTY_VALUE); -//--- result - return(ChartPriceOnDropped()); - } -//+------------------------------------------------------------------+ -//| Access function TimeOnDropped() | -//+------------------------------------------------------------------+ -datetime CChart::TimeOnDropped(void) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartTimeOnDropped()); - } -//+------------------------------------------------------------------+ -//| Access functions XOnDropped() | -//+------------------------------------------------------------------+ -int CChart::XOnDropped(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ChartXOnDropped()); - } -//+------------------------------------------------------------------+ -//| Access functions YOnDropped() | -//+------------------------------------------------------------------+ -int CChart::YOnDropped(void) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ChartYOnDropped()); - } -//+------------------------------------------------------------------+ -//| Adds indicator to chart | -//+------------------------------------------------------------------+ -bool CChart::IndicatorAdd(const int subwin,const int handle) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartIndicatorAdd(m_chart_id,subwin,handle)); - } -//+------------------------------------------------------------------+ -//| Deletes indicator from chart | -//+------------------------------------------------------------------+ -bool CChart::IndicatorDelete(const int subwin,const string name) const - { -//--- check - if(m_chart_id==-1) - return(false); -//--- result - return(ChartIndicatorDelete(m_chart_id,subwin,name)); - } -//+------------------------------------------------------------------+ -//| Gets number of indicators in chart subwindow | -//+------------------------------------------------------------------+ -int CChart::IndicatorsTotal(const int subwin) const - { -//--- check - if(m_chart_id==-1) - return(0); -//--- result - return(ChartIndicatorsTotal(m_chart_id,subwin)); - } -//+------------------------------------------------------------------+ -//| Gets short name of indicator | -//+------------------------------------------------------------------+ -string CChart::IndicatorName(const int subwin,const int index) const - { -//--- check - if(m_chart_id==-1) - return(""); -//--- result - return(ChartIndicatorName(m_chart_id,subwin,index)); - } -//+------------------------------------------------------------------+ -//| Writing parameters of chart to file | -//+------------------------------------------------------------------+ -bool CChart::Save(const int file_handle) - { - string work_str; - int work_int; -//--- check - if(file_handle==INVALID_HANDLE || m_chart_id==-1) - return(false); -//--- write start marker - 0xFFFFFFFFFFFFFFFF - if(FileWriteLong(file_handle,-1)!=sizeof(long)) - return(false); -//--- write chart type - if(FileWriteInteger(file_handle,Type(),INT_VALUE)!=INT_VALUE) - return(false); -//--- write chart symbol - work_str=Symbol(); - work_int=StringLen(work_str); - if(FileWriteInteger(file_handle,work_int,INT_VALUE)!=INT_VALUE) - return(false); - if(work_int!=0) if(FileWriteString(file_handle,work_str,work_int)!=work_int) - return(false); -//--- write period of chart - if(FileWriteInteger(file_handle,Period(),INT_VALUE)!=sizeof(int)) - return(false); -//--- write value of the "Mode" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_MODE),INT_VALUE)!=sizeof(int)) - return(false); -//--- write value of the "Foreground" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_FOREGROUND),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "Shift" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHIFT),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShiftSize" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHIFT),INT_VALUE)!=sizeof(int)) - return(false); -//--- write value of the "AutoScroll" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_AUTOSCROLL),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "Scale" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SCALE),INT_VALUE)!=sizeof(int)) - return(false); -//--- write value of the "ScaleFix" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SCALEFIX),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ScaleFix_11" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SCALEFIX_11),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "FixedMax" property - if(FileWriteDouble(file_handle,ChartGetDouble(m_chart_id,CHART_FIXED_MAX))!=sizeof(double)) - return(false); -//--- write value of the "FixedMin" property - if(FileWriteDouble(file_handle,ChartGetDouble(m_chart_id,CHART_FIXED_MIN))!=sizeof(double)) - return(false); -//--- write the "ScalePPB" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SCALE_PT_PER_BAR),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "PointsPerBar" property - if(FileWriteDouble(file_handle,ChartGetDouble(m_chart_id,CHART_POINTS_PER_BAR))!=sizeof(double)) - return(false); -//--- write value of the "ShowOHLC" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_OHLC),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowLineBid" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_BID_LINE),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowLineAsk" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_ASK_LINE),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowLastLine" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_LAST_LINE),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowPeriodSep" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_PERIOD_SEP),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowGrid" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_GRID),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- write value of the "ShowVolumes" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_VOLUMES),INT_VALUE)!=sizeof(int)) - return(false); -//--- write value of the "ShowObjectDescr" property - if(FileWriteInteger(file_handle,(int)ChartGetInteger(m_chart_id,CHART_SHOW_OBJECT_DESCR),CHAR_VALUE)!=sizeof(char)) - return(false); -//--- successful - return(true); - } -//+------------------------------------------------------------------+ -//| Reading parameters of chart from file | -//+------------------------------------------------------------------+ -bool CChart::Load(const int file_handle) - { - bool resutl=true; - string work_str; - int work_int; -//--- check - if(file_handle==INVALID_HANDLE || m_chart_id==-1) - return(false); -//--- read and checking start marker - 0xFFFFFFFFFFFFFFFF - if(FileReadLong(file_handle)!=-1) return(false); -//--- read and checking chart type - if(FileReadInteger(file_handle,INT_VALUE)!=Type()) return(false); -//--- read chart symbol - work_int=FileReadInteger(file_handle); - if(work_int!=0) work_str=FileReadString(file_handle,work_int); - else work_str=""; -//--- read chart period - work_int=FileReadInteger(file_handle); - SetSymbolPeriod(work_str,(ENUM_TIMEFRAMES)work_int); -//--- read value of the "Mode" property - if(!ChartSetInteger(m_chart_id,CHART_MODE,FileReadInteger(file_handle,INT_VALUE))) - return(false); -//--- read value of the "Foreground" property - if(!ChartSetInteger(m_chart_id,CHART_FOREGROUND,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "Shift" property - if(!ChartSetInteger(m_chart_id,CHART_SHIFT,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShiftSize" property - if(!ChartSetInteger(m_chart_id,CHART_SHIFT,FileReadInteger(file_handle,INT_VALUE))) - return(false); -//--- read value of the "AutoScroll" property - if(!ChartSetInteger(m_chart_id,CHART_AUTOSCROLL,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "Scale" property - if(!ChartSetInteger(m_chart_id,CHART_SCALE,FileReadInteger(file_handle,INT_VALUE))) - return(false); -//--- read value of the "ScaleFix" property - if(!ChartSetInteger(m_chart_id,CHART_SCALEFIX,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ScaleFix_11" property - if(!ChartSetInteger(m_chart_id,CHART_SCALEFIX_11,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "FixedMax" property - if(!ChartSetDouble(m_chart_id,CHART_FIXED_MAX,FileReadDatetime(file_handle))) - return(false); -//--- read value of the "FixedMin" property - if(!ChartSetDouble(m_chart_id,CHART_FIXED_MIN,FileReadDatetime(file_handle))) - return(false); -//--- read value of the "ScalePPB" property - if(!ChartSetInteger(m_chart_id,CHART_SCALE_PT_PER_BAR,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "PointsPerBar" property - if(!ChartSetDouble(m_chart_id,CHART_POINTS_PER_BAR,FileReadDatetime(file_handle))) - return(false); -//--- read value of the "ShowOHLC" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_OHLC,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowLineBid" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_BID_LINE,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowLineAsk" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_ASK_LINE,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowLastLine" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_LAST_LINE,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowPeriodSep" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_PERIOD_SEP,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowGrid" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_GRID,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- read value of the "ShowVolumes" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_VOLUMES,FileReadInteger(file_handle,INT_VALUE))) - return(false); -//--- read value of the "ShowObjectDescr" property - if(!ChartSetInteger(m_chart_id,CHART_SHOW_OBJECT_DESCR,FileReadInteger(file_handle,CHAR_VALUE))) - return(false); -//--- successful - return(resutl); - } -//+------------------------------------------------------------------+ diff --git a/Include/Controls/BmpButton.mqh b/Include/Controls/BmpButton.mqh deleted file mode 100644 index 080541d..0000000 --- a/Include/Controls/BmpButton.mqh +++ /dev/null @@ -1,268 +0,0 @@ -//+------------------------------------------------------------------+ -//| BmpButton.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "WndObj.mqh" -#include -//+------------------------------------------------------------------+ -//| Class CBmpButton | -//| Usage: control that is displayed by | -//| the CChartObjectBmpLabel object | -//+------------------------------------------------------------------+ -class CBmpButton : public CWndObj - { -private: - CChartObjectBmpLabel m_button; // chart object - //--- parameters of the chart object - int m_border; // border width - string m_bmp_off_name; // name of BMP file for the "OFF" state (default state) - string m_bmp_on_name; // name of BMP file for the "ON" state - string m_bmp_passive_name; - string m_bmp_active_name; - -public: - CBmpButton(void); - ~CBmpButton(void); - //--- create - virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); - //--- parameters of the chart object - int Border(void) const { return(m_border); } - bool Border(const int value); - bool BmpNames(const string off="",const string on=""); - string BmpOffName(void) const { return(m_bmp_off_name); } - bool BmpOffName(const string name); - string BmpOnName(void) const { return(m_bmp_on_name); } - bool BmpOnName(const string name); - string BmpPassiveName(void) const { return(m_bmp_passive_name); } - bool BmpPassiveName(const string name); - string BmpActiveName(void) const { return(m_bmp_active_name); } - bool BmpActiveName(const string name); - //--- state - bool Pressed(void) const { return(m_button.State()); } - bool Pressed(const bool pressed) { return(m_button.State(pressed)); } - //--- properties - bool Locking(void) const { return(IS_CAN_LOCK); } - void Locking(const bool locking); - -protected: - //--- handlers of object settings - virtual bool OnSetZOrder(void) { return(m_button.Z_Order(m_zorder)); } - //--- internal event handlers - virtual bool OnCreate(void); - virtual bool OnShow(void); - virtual bool OnHide(void); - virtual bool OnMove(void); - virtual bool OnChange(void); - //--- íîâûå îáðàáîò÷èêè - virtual bool OnActivate(void); - virtual bool OnDeactivate(void); - virtual bool OnMouseDown(void); - virtual bool OnMouseUp(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CBmpButton::CBmpButton(void) : m_border(0), - m_bmp_off_name(NULL), - m_bmp_on_name(NULL), - m_bmp_passive_name(NULL), - m_bmp_active_name(NULL) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CBmpButton::~CBmpButton(void) - { - } -//+------------------------------------------------------------------+ -//| Create a control | -//+------------------------------------------------------------------+ -bool CBmpButton::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) - { -//--- call method of the parent class - if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2)) - return(false); -//--- create the chart object - if(!m_button.Create(chart,name,subwin,x1,y1)) - return(false); -//--- call the settings handler - return(OnChange()); - } -//+------------------------------------------------------------------+ -//| Set border width | -//+------------------------------------------------------------------+ -bool CBmpButton::Border(const int value) - { -//--- save new value of parameter - m_border=value; -//--- set up the chart object - return(m_button.Width(value)); - } -//+------------------------------------------------------------------+ -//| Set two images at once | -//+------------------------------------------------------------------+ -bool CBmpButton::BmpNames(const string off,const string on) - { -//--- save new values of parameters - m_bmp_off_name=off; - m_bmp_on_name =on; -//--- set up the chart object - if(!m_button.BmpFileOff(off)) - return(false); - if(!m_button.BmpFileOn(on)) - return(false); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Set image for the "OFF" state | -//+------------------------------------------------------------------+ -bool CBmpButton::BmpOffName(const string name) - { -//--- save new value of parameter - m_bmp_off_name=name; -//--- set up the chart object - if(!m_button.BmpFileOff(name)) - return(false); -//--- set size by image dimensions - Width(m_button.X_Size()); - Height(m_button.Y_Size()); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Set image for the "ON" state | -//+------------------------------------------------------------------+ -bool CBmpButton::BmpOnName(const string name) - { -//--- save new value of parameter - m_bmp_on_name=name; -//--- set up the chart object - if(!m_button.BmpFileOn(name)) - return(false); -//--- set size by image dimensions - Width(m_button.X_Size()); - Height(m_button.Y_Size()); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Set image for the "OFF" state (passive) | -//+------------------------------------------------------------------+ -bool CBmpButton::BmpPassiveName(const string name) - { -//--- save new value of parameter - m_bmp_passive_name=name; -//--- set up the chart object - if(!IS_ACTIVE) - return(BmpOffName(name)); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Set image for the "OFF" state (active) | -//+------------------------------------------------------------------+ -bool CBmpButton::BmpActiveName(const string name) - { -//--- save new value of parameter - m_bmp_active_name=name; -//--- set up the chart object - if(IS_ACTIVE) - return(BmpOffName(name)); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Locking flag | -//+------------------------------------------------------------------+ -void CBmpButton::Locking(const bool flag) - { - if(flag) - PropFlagsSet(WND_PROP_FLAG_CAN_LOCK); - else - PropFlagsReset(WND_PROP_FLAG_CAN_LOCK); - } -//+------------------------------------------------------------------+ -//| Create object on chart | -//+------------------------------------------------------------------+ -bool CBmpButton::OnCreate(void) - { -//--- create the chart object by previously set parameters - return(m_button.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top)); - } -//+------------------------------------------------------------------+ -//| Display object on chart | -//+------------------------------------------------------------------+ -bool CBmpButton::OnShow(void) - { - return(m_button.Timeframes(OBJ_ALL_PERIODS)); - } -//+------------------------------------------------------------------+ -//| Hide object from chart | -//+------------------------------------------------------------------+ -bool CBmpButton::OnHide(void) - { - return(m_button.Timeframes(OBJ_NO_PERIODS)); - } -//+------------------------------------------------------------------+ -//| Absolute movement of the chart object | -//+------------------------------------------------------------------+ -bool CBmpButton::OnMove(void) - { -//--- position the chart object - return(m_button.X_Distance(m_rect.left) && m_button.Y_Distance(m_rect.top)); - } -//+------------------------------------------------------------------+ -//| Set up the chart object | -//+------------------------------------------------------------------+ -bool CBmpButton::OnChange(void) - { -//--- set up the chart object - return(m_button.Width(m_border) && m_button.BmpFileOff(m_bmp_off_name) && m_button.BmpFileOn(m_bmp_on_name)); - } -//+------------------------------------------------------------------+ -//| Handler of activating the group of controls | -//+------------------------------------------------------------------+ -bool CBmpButton::OnActivate(void) - { - if(m_bmp_active_name!=NULL) - BmpOffName(m_bmp_active_name); -//--- handled - return(true); - } -//+------------------------------------------------------------------+ -//| Handler of deactivating the group of controls | -//+------------------------------------------------------------------+ -bool CBmpButton::OnDeactivate(void) - { - if(m_bmp_passive_name!=NULL) - BmpOffName(m_bmp_passive_name); - if(!IS_CAN_LOCK) - Pressed(false); -//--- handled - return(true); - } -//+------------------------------------------------------------------+ -//| Handler of click on the left mouse button | -//+------------------------------------------------------------------+ -bool CBmpButton::OnMouseDown(void) - { - if(!IS_CAN_LOCK) - Pressed(!Pressed()); -//--- call of the method of the parent class - return(CWnd::OnMouseDown()); - } -//+------------------------------------------------------------------+ -//| Handler of click on the left mouse button | -//+------------------------------------------------------------------+ -bool CBmpButton::OnMouseUp(void) - { -//--- depress the button if it is not fixed - if(m_button.State() && !IS_CAN_LOCK) - m_button.State(false); -//--- call of the method of the parent class - return(CWnd::OnMouseUp()); - } -//+------------------------------------------------------------------+ diff --git a/Include/Controls/Button.mqh b/Include/Controls/Button.mqh deleted file mode 100644 index 08d5a76..0000000 --- a/Include/Controls/Button.mqh +++ /dev/null @@ -1,146 +0,0 @@ -//+------------------------------------------------------------------+ -//| Button.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "WndObj.mqh" -#include -//+------------------------------------------------------------------+ -//| Class CButton | -//| Usage: control that is displayed by | -//| the CChartObjectButton object | -//+------------------------------------------------------------------+ -class CButton : public CWndObj - { -private: - CChartObjectButton m_button; // chart object - -public: - CButton(void); - ~CButton(void); - //--- create - virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); - //--- state - bool Pressed(void) const { return(m_button.State()); } - bool Pressed(const bool pressed) { return(m_button.State(pressed)); } - //--- properties - bool Locking(void) const { return(IS_CAN_LOCK); } - void Locking(const bool flag); - -protected: - //--- handlers of object settings - virtual bool OnSetText(void) { return(m_button.Description(m_text)); } - virtual bool OnSetColor(void) { return(m_button.Color(m_color)); } - virtual bool OnSetColorBackground(void) { return(m_button.BackColor(m_color_background)); } - virtual bool OnSetColorBorder(void) { return(m_button.BorderColor(m_color_border)); } - virtual bool OnSetFont(void) { return(m_button.Font(m_font)); } - virtual bool OnSetFontSize(void) { return(m_button.FontSize(m_font_size)); } - //--- internal event handlers - virtual bool OnCreate(void); - virtual bool OnShow(void); - virtual bool OnHide(void); - virtual bool OnMove(void); - virtual bool OnResize(void); - //--- íîâûå îáðàáîò÷èêè - virtual bool OnMouseDown(void); - virtual bool OnMouseUp(void); - }; -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CButton::CButton(void) - { - m_color =CONTROLS_BUTTON_COLOR; - m_color_background=CONTROLS_BUTTON_COLOR_BG; - m_color_border =CONTROLS_BUTTON_COLOR_BORDER; - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CButton::~CButton(void) - { - } -//+------------------------------------------------------------------+ -//| Create a control | -//+------------------------------------------------------------------+ -bool CButton::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) - { -//--- call method of the parent class - if(!CWndObj::Create(chart,name,subwin,x1,y1,x2,y2)) - return(false); -//--- create the chart object - if(!m_button.Create(chart,name,subwin,x1,y1,Width(),Height())) - return(false); -//--- call the settings handler - return(OnChange()); - } -//+------------------------------------------------------------------+ -//| Locking flag | -//+------------------------------------------------------------------+ -void CButton::Locking(const bool flag) - { - if(flag) - PropFlagsSet(WND_PROP_FLAG_CAN_LOCK); - else - PropFlagsReset(WND_PROP_FLAG_CAN_LOCK); - } -//+------------------------------------------------------------------+ -//| Create object on chart | -//+------------------------------------------------------------------+ -bool CButton::OnCreate(void) - { -//--- create the chart object by previously set parameters - return(m_button.Create(m_chart_id,m_name,m_subwin,m_rect.left,m_rect.top,m_rect.Width(),m_rect.Height())); - } -//+------------------------------------------------------------------+ -//| Display object on chart | -//+------------------------------------------------------------------+ -bool CButton::OnShow(void) - { - return(m_button.Timeframes(OBJ_ALL_PERIODS)); - } -//+------------------------------------------------------------------+ -//| Hide object from chart | -//+------------------------------------------------------------------+ -bool CButton::OnHide(void) - { - return(m_button.Timeframes(OBJ_NO_PERIODS)); - } -//+------------------------------------------------------------------+ -//| Absolute movement of the chart object | -//+------------------------------------------------------------------+ -bool CButton::OnMove(void) - { -//--- position the chart object - return(m_button.X_Distance(m_rect.left) && m_button.Y_Distance(m_rect.top)); - } -//+------------------------------------------------------------------+ -//| Resize the chart object | -//+------------------------------------------------------------------+ -bool CButton::OnResize(void) - { -//--- resize the chart object - return(m_button.X_Size(m_rect.Width()) && m_button.Y_Size(m_rect.Height())); - } -//+------------------------------------------------------------------+ -//| Handler of click on the left mouse button | -//+------------------------------------------------------------------+ -bool CButton::OnMouseDown(void) - { - if(!IS_CAN_LOCK) - Pressed(!Pressed()); -//--- call of the method of the parent class - return(CWnd::OnMouseDown()); - } -//+------------------------------------------------------------------+ -//| Handler of click on the left mouse button | -//+------------------------------------------------------------------+ -bool CButton::OnMouseUp(void) - { -//--- depress the button if it is not fixed - if(m_button.State() && !IS_CAN_LOCK) - m_button.State(false); -//--- call of the method of the parent class - return(CWnd::OnMouseUp()); - } -//+------------------------------------------------------------------+ diff --git a/Include/Controls/CheckBox.mqh b/Include/Controls/CheckBox.mqh deleted file mode 100644 index e8186fd..0000000 --- a/Include/Controls/CheckBox.mqh +++ /dev/null @@ -1,183 +0,0 @@ -//+------------------------------------------------------------------+ -//| CheckBox.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "WndContainer.mqh" -#include "BmpButton.mqh" -#include "Edit.mqh" -//+------------------------------------------------------------------+ -//| Resources | -//+------------------------------------------------------------------+ -#resource "res\\CheckBoxOn.bmp" -#resource "res\\CheckBoxOff.bmp" -//+------------------------------------------------------------------+ -//| Class CCheckBox | -//| Usage: class that implements the "CheckBox" control | -//+------------------------------------------------------------------+ -class CCheckBox : public CWndContainer - { -private: - //--- dependent controls - CBmpButton m_button; // button object - CEdit m_label; // label object - //--- data - int m_value; // value - -public: - CCheckBox(void); - ~CCheckBox(void); - //--- create - virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); - //--- chart event handler - virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); - //--- settings - string Text(void) const { return(m_label.Text()); } - bool Text(const string value) { return(m_label.Text(value)); } - color Color(void) const { return(m_label.Color()); } - bool Color(const color value) { return(m_label.Color(value)); } - //--- state - bool Checked(void) const { return(m_button.Pressed()); } - bool Checked(const bool flag) { return(m_button.Pressed(flag)); } - //--- data - int Value(void) const { return(m_value); } - void Value(const int value) { m_value=value; } - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - -protected: - //--- create dependent controls - virtual bool CreateButton(void); - virtual bool CreateLabel(void); - //--- handlers of the dependent controls events - virtual bool OnClickButton(void); - virtual bool OnClickLabel(void); - }; -//+------------------------------------------------------------------+ -//| Common handler of chart events | -//+------------------------------------------------------------------+ -EVENT_MAP_BEGIN(CCheckBox) - ON_EVENT(ON_CLICK,m_button,OnClickButton) - ON_EVENT(ON_CLICK,m_label,OnClickLabel) -EVENT_MAP_END(CWndContainer) -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CCheckBox::CCheckBox(void) : m_value(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CCheckBox::~CCheckBox(void) - { - } -//+------------------------------------------------------------------+ -//| Create a control | -//+------------------------------------------------------------------+ -bool CCheckBox::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) - { -//--- call method of the parent class - if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2)) - return(false); -//--- create dependent controls - if(!CreateButton()) - return(false); - if(!CreateLabel()) - return(false); -//--- succeeded - return(true); - } -//+------------------------------------------------------------------+ -//| Create button | -//+------------------------------------------------------------------+ -bool CCheckBox::CreateButton(void) - { -//--- calculate coordinates - int x1=CONTROLS_CHECK_BUTTON_X_OFF; - int y1=CONTROLS_CHECK_BUTTON_Y_OFF; - int x2=x1+CONTROLS_BUTTON_SIZE; - int y2=y1+CONTROLS_BUTTON_SIZE-CONTROLS_BORDER_WIDTH; -//--- create - if(!m_button.Create(m_chart_id,m_name+"Button",m_subwin,x1,y1,x2,y2)) - return(false); - if(!m_button.BmpNames("::res\\CheckBoxOff.bmp","::res\\CheckBoxOn.bmp")) - return(false); - if(!Add(m_button)) - return(false); - m_button.Locking(true); -//--- succeeded - return(true); - } -//+------------------------------------------------------------------+ -//| Create label | -//+------------------------------------------------------------------+ -bool CCheckBox::CreateLabel(void) - { -//--- calculate coordinates - int x1=CONTROLS_CHECK_LABEL_X_OFF; - int y1=CONTROLS_CHECK_LABEL_Y_OFF; - int x2=Width(); - int y2=Height(); -//--- create - if(!m_label.Create(m_chart_id,m_name+"Label",m_subwin,x1,y1,x2,y2)) - return(false); - if(!m_label.Text(m_name)) - return(false); - if(!Add(m_label)) - return(false); - m_label.ReadOnly(true); - m_label.ColorBackground(CONTROLS_CHECKGROUP_COLOR_BG); - m_label.ColorBorder(CONTROLS_CHECKGROUP_COLOR_BG); -//--- succeeded - return(true); - } -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -bool CCheckBox::Save(const int file_handle) - { -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- - FileWriteInteger(file_handle,Checked()); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -bool CCheckBox::Load(const int file_handle) - { -//--- check - if(file_handle==INVALID_HANDLE) - return(false); -//--- - if(!FileIsEnding(file_handle)) - Checked(FileReadInteger(file_handle)); -//--- succeed - return(true); - } -//+------------------------------------------------------------------+ -//| Handler of click on button | -//+------------------------------------------------------------------+ -bool CCheckBox::OnClickButton(void) - { -//--- send the "changed state" event - EventChartCustom(CONTROLS_SELF_MESSAGE,ON_CHANGE,m_id,0.0,m_name); -//--- handled - return(true); - } -//+------------------------------------------------------------------+ -//| Handler of click on label | -//+------------------------------------------------------------------+ -bool CCheckBox::OnClickLabel(void) - { -//--- change button state - m_button.Pressed(!m_button.Pressed()); -//--- return the result of the button click handler - return(OnClickButton()); - } -//+------------------------------------------------------------------+ diff --git a/Include/Controls/CheckGroup.mqh b/Include/Controls/CheckGroup.mqh deleted file mode 100644 index 6d5de34..0000000 --- a/Include/Controls/CheckGroup.mqh +++ /dev/null @@ -1,377 +0,0 @@ -//+------------------------------------------------------------------+ -//| CheckGroup.mqh | -//| Copyright 2009-2017, MetaQuotes Software Corp. | -//| http://www.mql5.com | -//+------------------------------------------------------------------+ -#include "WndClient.mqh" -#include "CheckBox.mqh" -#include -#include -#include -//+------------------------------------------------------------------+ -//| Class CCheckGroup | -//| Usage: view and edit group of flags | -//+------------------------------------------------------------------+ -class CCheckGroup : public CWndClient - { -private: - //--- dependent controls - CCheckBox m_rows[]; // array of the row objects - //--- set up - int m_offset; // index of first visible row in array of rows - int m_total_view; // number of visible rows - int m_item_height; // height of visible row - //--- data - CArrayString m_strings; // array of rows - CArrayLong m_values; // array of values - CArrayInt m_states; // array of states - long m_value; // current value - int m_current; // index of current row in array of rows - -public: - CCheckGroup(void); - ~CCheckGroup(void); - //--- create - virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2); - virtual void Destroy(const int reason=0); - //--- chart event handler - virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); - //--- fill - virtual bool AddItem(const string item,const long value=0); - //--- data - long Value(void) const; - bool Value(const long value); - int Check(const int idx) const; - bool Check(const int idx,const int value); - //--- state - virtual bool Show(void); - //--- methods for working with files - virtual bool Save(const int file_handle); - virtual bool Load(const int file_handle); - -protected: - //--- create dependent controls - bool CreateButton(int index); - //--- handlers of the dependent controls events - virtual bool OnVScrollShow(void); - virtual bool OnVScrollHide(void); - virtual bool OnScrollLineDown(void); - virtual bool OnScrollLineUp(void); - virtual bool OnChangeItem(const int row_index); - //--- redraw - bool Redraw(void); - bool RowState(const int index,const bool select); - }; -//+------------------------------------------------------------------+ -//| Common handler of chart events | -//+------------------------------------------------------------------+ -EVENT_MAP_BEGIN(CCheckGroup) - ON_INDEXED_EVENT(ON_CHANGE,m_rows,OnChangeItem) -EVENT_MAP_END(CWndClient) -//+------------------------------------------------------------------+ -//| Constructor | -//+------------------------------------------------------------------+ -CCheckGroup::CCheckGroup(void) : m_offset(0), - m_total_view(0), - m_item_height(CONTROLS_LIST_ITEM_HEIGHT), - m_current(CONTROLS_INVALID_INDEX), - m_value(0) - { - } -//+------------------------------------------------------------------+ -//| Destructor | -//+------------------------------------------------------------------+ -CCheckGroup::~CCheckGroup(void) - { - } -//+------------------------------------------------------------------+ -//| Create a control | -//+------------------------------------------------------------------+ -bool CCheckGroup::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2) - { -//--- determine the number of visible rows - m_total_view=(y2-y1)/m_item_height; -//--- check the number of visible rows - if(m_total_view<1) - return(false); -//--- call method of the parent class - if(!CWndClient::Create(chart,name,subwin,x1,y1,x2,y2)) - return(false); -//--- set up - if(!m_background.ColorBackground(CONTROLS_CHECKGROUP_COLOR_BG)) - return(false); - if(!m_background.ColorBorder(CONTROLS_CHECKGROUP_COLOR_BORDER)) - return(false); -//--- create dependent controls - ArrayResize(m_rows,m_total_view); - for(int i=0;i=m_values.Total()) - return(0); -//--- - return(m_states[idx]); - } -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ -bool CCheckGroup::Check(const int idx,const int value) - { -//--- check - if(idx>=m_values.Total()) - return(false); -//--- - bool res=(m_states.Update(idx,value) && Redraw()); -//--- change value - if(res && idx<64) - { - if(m_rows[idx].Checked()) - Value(m_value|m_values.At(idx)); - else - Value(m_value&(~m_values.At(idx))); - } -//--- - return(res); - } -//+------------------------------------------------------------------+ -//| Makes the group visible | -//+------------------------------------------------------------------+ -bool CCheckGroup::Show(void) - { -//--- call of the method of the parent class - if(!CWndClient::Show()) - return(false); -//--- loop by rows - int total=m_values.Total(); - for(int i=total;i=ArraySize(m_rows)) - return(true); -//--- change state - return(m_rows[index].Checked(select)); - } -//+------------------------------------------------------------------+ -//| Handler of the "Show vertical scrollbar" event | -//+------------------------------------------------------------------+ -bool CCheckGroup::OnVScrollShow(void) - { -//--- loop by "rows" - for(int i=0;i