I'm making a custom indicator.
I want to show theoretical brake out lines. So like, straight horizontal line segments. At the moment I have it working, using the semantics of DRAW_SECTION, except - obviously - all my segments are connected.
Is there a way to hide sections of the line that I don't need?
Or is there a better way to do it?
Two scenarios:
1.
SetIndexStyle( i, DRAW_NONE ); where i is the number of your buffer.
2.
#property indicator_buffers 3
IndicatorBuffers(4);
where
3 is a number of buffers to display,
4 is a total number of buffers. Even though you cannot see the buffer line on the chart, it is still accessed by iCustom( _Symbol, 0, indicator_name, ..., 3, shift );
where 3 is a zero-based reference to the buffer #4.
There is a way in MQL4 Indicators :
As documented, there is a special value == EMPTY_VALUE to serve exactly this purpose.
The EMPTY_VALUE constant usually corresponds to the values of indicators that are not shown in the chart.
Just assign, where plausible in your indicator code - either per-bar in assignment BreakOutBUFFER[i] = ( isHereBreakOut( i ) ) ? aLevel : EMPTY_VALUE;
or
by a pre-initialised ArrayInitialize( BreakOutBUFFER, EMPTY_VALUE ); and re-assigning only those cells, where your BreakOut-logic is POSACK'd, yet this is not a preferred way, as the first sooner-or-later coming ( automatic or not ) ArrayResize() will extend this Buffer, as documented:
... the elements will be added at the end of the array, their values will be undefined and in most cases will not be equal to init_value.
but .... not with the pre-set EMPTY_VALUE initialiser...
My option is, obviously, to go the former way
Related
Fairly new to Delphi, so forgive me if this is a trivial question.
I have the following:
TMsgDlgBtn = (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore,
mbAll, mbNoToAll, mbYesToAll, mbHelp, mbClose);
TMsgDlgButtons = set of TMsgDlgBtn;
and this loop:
//Buttons is of type TMsgDlgButtons and value is [mbRetry, mbCancel]
for B := Low(TMsgDlgBtn) to High(TMsgDlgBtn) do
if B in Buttons then
//Do something with the button B
It seems like no matter which order Buttons is in, it is always processed with mbCancel first, then mbRetry second. I saw that this is because of the order of TMsgDlgBtn so I tried this instead:
for B in Buttons do
//Do something with the button B
but it seems to iterate the same way - cancel first, then retry.
Is this because Buttons is a set? Is there any way to iterate through Buttons such that the order is respected?
Is there any way to iterate through Buttons such that the order is respected?
No, because the set doesn't hold the information of, in which order the set members were assigned to the set.
Explanation:
First you declare an enumeration type, TMsgDlgBtn. As you did not define any specific values, they are given the values 0, 1, 2, 3 ...
Then you declare the set type, TMsgDlgButtons. For members of sets, one bit is reserved for each value. So, 12 bits represent the membership of the buttons in the set.
When you assign Buttons := [mbRetry, mbCancel] the corresponding bits of those buttons are set in the Buttons set. The implementation of the first for loop checks the membership from the lowest to the highest bit, so it is natural that the test is performed on mbCancel before mbRetry. The implementation of the second for loop, is likely done in the same order, from lower to higher bits.
I get this error on compilation in MetaTrader:
indicator buffers amount is less than needed
any help?
MQL4 Indicator setup may look as a dual-headed nightmare.Maybe yes,maybe no:
There are two principal methods used for an Indicator setup.
one, using #property ... syntax interface,
and
another, using function calls ...
Why these two exist? How do they co-exist?
#property ...
indicator_chart_window Show the indicator in the chart window
indicator_separate_window Show the indicator in a separate window
indicator_height int Fixed height of the indicator subwindow in pixels (property INDICATOR_HEIGHT)
indicator_buffers int Number of buffers for indicator calculation
indicator_minimum double The bottom scaling limit for a separate indicator window
indicator_maximum double The top scaling limit for a separate indicator window
indicator_labelN string Sets a label for the N-th graphic series displayed in DataWindow
indicator_colorN color The color for displaying line N, where N is the number of graphic series; numbering starts from 1
indicator_widthN int Line thickness in graphic series, where N is the number of graphic series; numbering starts from 1
indicator_styleN int Line style in graphic series, specified by the values of ENUM_LINE_STYLE. N is the number of graphic series; numbering starts from 1
indicator_typeN int Type of indicator drawing style. N is the number of graphic series; numbering starts from 1
indicator_levelN double Horizontal level of N in a separate indicator window
indicator_levelcolor color Color of horizontal levels of the indicator
indicator_levelwidth int Thickness of horizontal levels of the indicator
indicator_levelstyle int Style of horizontal levels of the indicator
After some time in MQL4 you will adopt your own best way to go forwards.
Why failed to work?
Short version: a compile-time decision sets the amount of arrays preset for indicator time-series aligned data. Going past this set ceiling then must throw an exception as there is no further buffer to store data in.
However, setting a much bigger ceiling first is possible and may help, somewhere at a later time, to have still space enough, even when you do not use it right now.
That seems to be a problem of:
#property indicator_buffers XXX //How Many Plots
XXX should be correct number of Buffers/plots
Using CGContext, drawing a dashed line starting with a painted segment is easy:
using (var ctx = UIGraphics.GetCurrentContext())
{
ctx.BeginPath();
//... draw a path here
var pattern = new float[] { 2, 2 };
ctx.SetLineDash(0, pattern);
ctx.DrawPath(CGPathDrawingMode.Stroke);
}
This draws a line looking like this "xx--xx--xx--xx--", where "x" means painted, and "-" means not painted.
Now I want to draw a line starting with an unpainted segment, that is: "--xx--xx--xx--xx". Is there an elegant way to achieve this? E.g. by telling iOS to start with an unpainted segment?
Given our example, a line starting with unpainted segments can be achieved using the phase parameter:
using (var ctx = UIGraphics.GetCurrentContext())
{
ctx.BeginPath();
//... draw a path here
var pattern = new float[] { 2, 2 };
ctx.SetLineDash(2, pattern);
ctx.DrawPath(CGPathDrawingMode.Stroke);
}
However, for more complex patterns (something like { 2, 4, 3, 7, 5, 6 }) using the phase parameter becomes more cumbersome. The pattern probably needs to be shifted in addition to the phase parameter.
To wrap up: Is it possible to elegantly create a line dash starting with an unpainted segment, without using the phase parameter?
Note: The code examples are written in C# (MonoTouch), but the question applies to native iOS code as well.
Simple solution
Using only the line dash feature, the given problem cannot be solved without the phase parameter. It can be solved by re-ordering the dash array, and setting a phase.
To start with an unpainted segment, move the last dash array entry to the front, and set a phase with the same value. E.g. when the pattern -xx-xx-xx-xx-xx... is desired, the dash array 1, 2 with phase 0 would lead to a pattern like x--x--x--x--.... The dash array 2, 1 with phase 2 would lead to the pattern -xx-xx-xx-xx-xx..., as desired.
Extended solution with adapted pattern repeating
It seems iOS always alternates between painted and unpainted segments, and does not reset when the dash array is repeated. So e.g. the dash array 1, 2, 1 would result in a line pattern looking like x--x-xx-x--x.... In our case, we wanted the whole pattern to repeat. That is, with the given dash array, the line pattern should look like x--xx--xx--xx....
To achieve that, we need to ensure that the dash array always has an even number of elements. In addition to re-ordering the dash array and setting a phase, we need to adapt and remove elements. There are four cases to consider.
1. Start with painted segment, even number of segments.
Nothing to do here. Use dash array as is. Phase is 0.
2. Start with unpainted segment, even number of segments.
Move the last dash array entry to the front, and set a phase with the same value. Refer to the simple example above.
3. Start with painted segment, odd number of segments.
Add the last dash array entry to the first entry. Remove the last entry. Set a phase equal to the original last dash array entry.
E.g. the dash array 1, 2, 1 would normally lead to a pattern x--x-xx-.... The dash array 2, 2 with a phase of 1 leads to the desired pattern x--xx--xx--....
4. Start with unpainted segment, odd number of segments.
Add the first dash array entry to the last entry. Remove the first entry. Set a phase equal to the sum of all entries minus the original first dash array entry (this essentially lets the pattern start near the end, exactly where we added the original first entry to the last entry).
E.g. the dash array 1, 2, 1 would normally lead to a pattern x--x-xx-.... The pattern 2, 2 with a phase of 3 leads to the desired pattern -xx--xx--xx....
Alternatives
An alternative which does not use line dash feature could be the one described by #user2320861. #user2320861 suggests to paint over a solid line with a patterned line, using the background color. This should work well when the background color is known, and a uniform background is used.
A variant for diverse backgrounds (e.g. images) could be to set a clipping mask (CGContextClipToMask) by drawing a patterned line. Then a solid line could be drawn with this clipping mask.
I ploted some arrows in my MQL4 indicator so i am able to increase the width of the arrow but i want to increase the height of the arrow only so please help me.
The arrow symbols do not have separate adjust-ability in width and height, its just 'size'. An option would be to plot the arrow head, then draw a trend line object vertically above it to the length that you want.
MQL4 solution
Indicator can instruct an Arrow instance to have "bigger" size using OBJPROP_WIDTH instance attribute:
{ string anInterimObjNAME = "S" + sSellCntr;
ObjectCreate( anInterimObjNAME, OBJ_ARROW, 0, Time[0], Bid );
ObjectSet( anInterimObjNAME, OBJPROP_COLOR, Red );
if ( Action == 0 ) ObjectSet( anInterimObjNAME, OBJPROP_ARROWCODE, 1 );
if ( Action < 0 ) ObjectSet( anInterimObjNAME, OBJPROP_ARROWCODE, 5 );
ObjectSet( anInterimObjNAME, OBJPROP_WIDTH, 1 ); //<--
//ObjectSet( anInterimObjNAME, OBJPROP_WIDTH, 32 );//<--
}
New-MQL4 extension
Since Build 509+ there started to be new and new modifications of the MQL4 language syntax. So far, many times opening an integrated help system launches just another language update, so be carefull on coding limits, suddenly changed or unsupported syntax elements and even check several new syntax constructs. This is the life as it goes.
So, for the OBJ_ARROW, there is a possibility to extend it's size beyond a value of 5, which is ( as of Build 670 ) a limit for a manual GUI entry.
Help says:
Large arrows (more than 5) can only be created
by setting the appropriate OBJPROP_WIDTH property value
when writing a code in MetaEditor.
So, manually you still cannot enter more than 5, but via MQL4 code, you can go BIGGER :o)
I'm trying to use the DepthBias property on the rasterizer state in DirectX 11 (D3D11_RASTERIZER_DESC) to help with the z-fighting that occurs when I render in wireframe mode over solid polygons (wireframe overlay), and it seems setting it to any value doesn't change anything to the result. But I noticed something strange... the value is defined as a INT rather than a FLOAT. That doesn't make sense to me, but it still doesn't happen to work as expected. How do we properly set that value if it is a INT that needs to be interpreted as a UNORM in the shader pipeline?
Here's what I do:
Render all geometry
Set the rasterizer to render in wireframe
Render all geometry again
I can clearly see the wireframe overlay, but the z-fighting is horrible. I tried to set the DepthBias to a lot of different values, such as 0.000001, 0.1, 1, 10, 1000 and all the minus equivalent, still no results... obviously, I'm aware when casting the float as integer, all the decimals get cut... meh?
D3D11_RASTERIZER_DESC RasterizerDesc;
ZeroMemory(&RasterizerDesc, sizeof(RasterizerDesc));
RasterizerDesc.FillMode = D3D11_FILL_WIREFRAME;
RasterizerDesc.CullMode = D3D11_CULL_BACK;
RasterizerDesc.FrontCounterClockwise = FALSE;
RasterizerDesc.DepthBias = ???
RasterizerDesc.SlopeScaledDepthBias = 0.0f;
RasterizerDesc.DepthBiasClamp = 0.0f;
RasterizerDesc.DepthClipEnable = TRUE;
RasterizerDesc.ScissorEnable = FALSE;
RasterizerDesc.MultisampleEnable = FALSE;
RasterizerDesc.AntialiasedLineEnable = FALSE;
As anyone figured out how to set the DepthBias properly? Or perhaps it is a bug in DirectX (which I doubt) or again maybe there's a better way to achieve this than using DepthBias?
Thank you!
http://msdn.microsoft.com/en-us/library/windows/desktop/cc308048(v=vs.85).aspx
Depending on whether your depth buffer is UNORM or floating point varies the meaning of the number. In most cases you're just looking for the smallest possible value that gets rid of your z-fighting rather than any specific value. Small values are a small bias, large values are a large bias, but how that equates to a shift numerically depends on the format of your depth buffer.
As for the values you've tried, anything less than 1 would have rounded to zero and had no effect. 1, 10, 1000 may simply not have been enough to fix the issue. In the case of a D24 UNORM depth buffer, the formula would suggest a depth bias of 1000 would offset depth by: 1000 * (1 / 2^24), which equals 0.0000596, a not very significant shift in z-buffering terms.
Does a large value of 100,000 or 1,000,000 fix the z-fighting?
If anyone cares, I made myself a macro to make it easier. Note that this macro will only work if you are using a 32bit float depth buffer format. A different macro might be needed if you are using a different depth buffer format.
#define DEPTH_BIAS_D32_FLOAT(d) (d/(1/pow(2,23)))
That way you can simply set your depth bias using standard values, such as:
RasterizerDesc.DepthBias = DEPTH_BIAS_D32_FLOAT(-0.00001);