I have seen this code for the SRL6 Simba scripting language based on Delphi
dist:= hypot(xs - xe, ys - ye);
wind:= minE(wind, dist);
if (dist < 1) then
dist := 1;
PDist := (dist/TDist);
And
if (getSystemTime() > t) then
break;
dist:= hypot(xs - xe, ys - ye);
wind:= minE(wind, dist);
Really, we are focusing on the bottom line of the last snippet - minE(..). What could this function mean? I know it's mathematical, and yes I've Googled for an hour with no avail! Thanks for the help
MinE is only a wrapper for extended values. As seen in this example:
function ps_MinE(a, b : extended) : extended; extdecl;
begin
result := min(a,b);
end;
Related
I need to test if a point hits a polygon with holes and isles. I'd like to understand how I'm supposed to do this. That's not documented and I can't find any explanation or examples.
What I do is count +1 for every outer polygon hit and -1 for every inner polygon hit. The resulting sum is:
> 0: hit;
<= 0: miss (outside or in a hole).
The HitData class separates paths based on winding number to avoid unnecessary recomputation of orientation. With Clipper.PointInPolygon() applied to every path the sum is easy to compute.
But there are two major drawbacks:
I have to apply Clipper.PointInPolygon() to EVERY path;
I can't leverage the hierarchy of PolyTree.
Can someone who has hands-on experience with Clipper (#angus-johnson?) clear up this confusion?
Again, my question is: how am I supposed to implement this? Am I re-inventing the wheel, while there's an actual solution readily available in the Clipper Library?
Side note: PolyTree still requires to test EVERY path to determine which PolyNode the point is in. There's no Clipper.PointInPolyTree() method and, thus, AFAIK PolyTree doesn't help.
The structure that separates outer and inner polygons:
public class HitData
{
public List<List<IntPoint>> Outer, Inner;
public HitData(List<List<IntPoint>> paths)
{
Outer = new List<List<IntPoint>>();
Inner = new List<List<IntPoint>>();
foreach (List<IntPoint> path in paths)
{
if (Clipper.Orientation(path))
{
Outer.Add(path);
} else {
Inner.Add(path);
}
}
}
}
And this is the algorithm that tests a point:
public static bool IsHit(HitData data, IntPoint point)
{
int hits;
hits = 0;
foreach (List<IntPoint> path in data.Outer)
{
if (Clipper.PointInPolygon(point, path) != 0)
{
hits++;
}
}
foreach (List<IntPoint> path in data.Inner)
{
if (Clipper.PointInPolygon(point, path) != 0)
{
hits--;
}
}
return hits > 0;
}
Can someone who has hands-on experience with Clipper (#angus-johnson?) clear up this confusion?
It's not clear to me what your confusion is. As you've correctly observed, the Clipper library does not provide a function to determine whether a point is inside multiple paths.
Edit (13 Sept 2019):
OK, I've now created a PointInPaths function (in Delphi Pascal) that determines whether a point is inside multiple paths. Note that this function accommodates the different polygon filling rules.
function CrossProduct(const pt1, pt2, pt3: TPointD): double;
var
x1,x2,y1,y2: double;
begin
x1 := pt2.X - pt1.X;
y1 := pt2.Y - pt1.Y;
x2 := pt3.X - pt2.X;
y2 := pt3.Y - pt2.Y;
result := (x1 * y2 - y1 * x2);
end;
function PointInPathsWindingCount(const pt: TPointD;
const paths: TArrayOfArrayOfPointD): integer;
var
i,j, len: integer;
p: TArrayOfPointD;
prevPt: TPointD;
isAbove: Boolean;
crossProd: double;
begin
//nb: returns MaxInt ((2^32)-1) when pt is on a line
Result := 0;
for i := 0 to High(paths) do
begin
j := 0;
p := paths[i];
len := Length(p);
if len < 3 then Continue;
prevPt := p[len-1];
while (j < len) and (p[j].Y = prevPt.Y) do inc(j);
if j = len then continue;
isAbove := (prevPt.Y < pt.Y);
while (j < len) do
begin
if isAbove then
begin
while (j < len) and (p[j].Y < pt.Y) do inc(j);
if j = len then break
else if j > 0 then prevPt := p[j -1];
crossProd := CrossProduct(prevPt, p[j], pt);
if crossProd = 0 then
begin
result := MaxInt;
Exit;
end
else if crossProd < 0 then dec(Result);
end else
begin
while (j < len) and (p[j].Y > pt.Y) do inc(j);
if j = len then break
else if j > 0 then prevPt := p[j -1];
crossProd := CrossProduct(prevPt, p[j], pt);
if crossProd = 0 then
begin
result := MaxInt;
Exit;
end
else if crossProd > 0 then inc(Result);
end;
inc(j);
isAbove := not isAbove;
end;
end;
end;
function PointInPaths(const pt: TPointD;
const paths: TArrayOfArrayOfPointD; fillRule: TFillRule): Boolean;
var
wc: integer;
begin
wc := PointInPathsWindingCount(pt, paths);
case fillRule of
frEvenOdd: result := Odd(wc);
frNonZero: result := (wc <> 0);
end;
end;
With regards leveraging the PolyTree structure:
The top nodes in PolyTree are outer nodes that together contain every (nested) polygon. So you'll only need to perform PointInPolygon on these top nodes until a positive result is found. Then repeat PointInPolygon on that nodes nested paths (if any) looking for a positive match there. Obviously when an outer node fails PointInPolygon test, then its nested nodes (polygons) will also fail. Outer nodes will increment the winding count and inner holes will decrement the winding count.
I have this Ada package code which theoretically is well written:
with Ada.Text_IO;
with Ada.Characters.Handling;
package body pkg_procedure is
procedure Read_Integer(Num : out Integer) is
Intro : constant Character := ASCII.LF;
Back : constant Character := ASCII.Del;
Char : Character;
Fin : Boolean := False;
Number : Natural := 0;
String_Number : String (1 .. Integer'Width – 1);
begin
Ada.Text_IO.New_line;
Ada.Text_IO.Put ("Write down a number and press Enter: ");
while not Fin loop
Ada.Text_IO.Get_Immediate (Char);
if Ada.Characters.Handling.Is_Digit (Char) then
Number := Number + 1;
String_Number(Number) := Char;
Ada.Text_IO.Put (Char);
elsif Char = Intro then
Fin := True;
elsif Number > 0 and Char = Back then
Ada.Text_IO.Put (ASCII.BS & ' ' & ASCII.BS);
Number := Number + 1;
end if;
end loop;
Number := Integer'Value (String_Number (1 .. Number));
Ada.Text_IO.New_line;
Num := Number;
exception
when Constraint_Error =>
Ada.Text_IO.New_line;
Ada.Text_IO.Put_Line ("Sorry: " & String_Number & " is too long to store it");
Num := 0;
end Read_Integer;
end pkg_procedure;
When I compile the program I obtain an error on this instruction which says: binary operator expected.
I can't fix it. I am totally new to this programming language.
The problem turns out to be that the - in
String_Number : String (1 .. Integer'Width – 1);
isn’t a plain - but a wide character with encoding e28093 - EN DASH.
I found this because, having seen that various exploratory changes didn’t show the error, I reverted to your original and tried compiling with -gnatw8 (input is UTF-8) as well as -gnatl for mixing messages with the program text, which resulted in
13. String_Number : String (1 .. Integer'Width – 1);
12
>>> binary operator expected
>>> illegal wide character
I suspect you provided us the wrong part of your code as this
with Ada.Text_Io; use Ada.Text_Io;
procedure TestInt is
number : String (1 .. Integer'Width - 1);
begin
Put_Line("Width=" & Integer'Image(Integer'Width - 1));
end TestInt;
works like a charm, if we ignore the warning on number which is not used, and return as expected :
Width= 10
Please be more precise and provide a full compilable sample.
I might also be interesting to tell us which compiler you use and on which operating system.
I'm expanding a class of mine for storing generic size strings to allow more flexible values for user input. For example, my prior version of this class was strict and allowed only the format of 2x3 or 9x12. But now I'm making it so it can support values such as 2 x 3 or 9 X 12 and automatically maintain the original user's formatting if the values get changed.
The real question I'm trying to figure out is just how to detect if one character from a string is either upper or lower case? Because I have to detect case sensitivity. If the deliminator is 'x' (lowercase) and the user inputs 'X' (uppercase) inside the value, and case sensitivity is turned off, I need to be able to find the opposite-case as well.
I mean, the Pos() function is case sensitive...
Delphi 7 has UpperCase() and LowerCase() functions for strings. There's also UpCase() for characters.
If I want to search for a substring within another string case insensitively, I do this:
if Pos('needle', LowerCase(hayStack)) > 0 then
You simply use lower case string literals (or constants) and apply the lowercase function on the string before the search. If you'll be doing a lot of searches, it makes sense to convert just once into a temp variable.
Here's your case:
a := '2 x 3'; // Lowercase x
b := '9 X 12'; // Upper case X
x := Pos('x', LowerCase(a)); // x = 3
x := Pos('x', LowerCase(b)); // x = 3
To see if a character is upper or lower, simply compare it against the UpCase version of it:
a := 'A';
b := 'b';
upper := a = UpCase(a); // True
upper := b = UpCase(b); // False
try using these functions (which are part of the Character unit)
Character.TCharacter.IsUpper
Character.TCharacter.IsLower
IsLower
IsUpper
UPDATE
For ansi versions of delphi you can use the GetStringTypeEx functions to fill a list with each ansi character type information. and thne compare the result of each element against the $0001(Upper Case) or $0002(Lower Case) values.
uses
Windows,
SysUtils;
Var
LAnsiChars: array [AnsiChar] of Word;
procedure FillCharList;
var
lpSrcStr: AnsiChar;
lpCharType: Word;
begin
for lpSrcStr := Low(AnsiChar) to High(AnsiChar) do
begin
lpCharType := 0;
GetStringTypeExA(LOCALE_USER_DEFAULT, CT_CTYPE1, #lpSrcStr, SizeOf(lpSrcStr), lpCharType);
LAnsiChars[lpSrcStr] := lpCharType;
end;
end;
function CharIsLower(const C: AnsiChar): Boolean;
const
C1_LOWER = $0002;
begin
Result := (LAnsiChars[C] and C1_LOWER) <> 0;
end;
function CharIsUpper(const C: AnsiChar): Boolean;
const
C1_UPPER = $0001;
begin
Result := (LAnsiChars[C] and C1_UPPER) <> 0;
end;
begin
try
FillCharList;
Writeln(CharIsUpper('a'));
Writeln(CharIsUpper('A'));
Writeln(CharIsLower('a'));
Writeln(CharIsLower('A'));
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
Readln;
end.
if myChar in ['A'..'Z'] then
begin
// uppercase
end
else
if myChar in ['a'..'z'] then
begin
// lowercase
end
else
begin
// not an alpha char
end;
..or D2009 on..
if charInSet(myChar,['A'..'Z']) then
begin
// uppercase
end
else
if charInSet(myChar,['a'..'z']) then
begin
// lowercase
end
else
begin
// not an alpha char
end;
The JCL has routines for this in the JclStrings unit, eg CharIsUpper and CharIsLower. SHould work in Delphi 7.
AnsiPos() is not case-sensitive. You can also force upper or lower case, irrespective of what the user enters using UpperCase() and LowerCase().
Just throwing this out there since you may find it far more simple than the other (very good) answers.
I am currently developing an application in Delphi, in which I have to hide (obfuscate) a string in source code like str := 'Example String'.
Why ? Because if I open the EXE in text editor and search for Example String I'll find the string in second...
I tried to use a basic HEX transcription like #$65#$78#$61#$6d#$70#$6c#$65 but it's re-transcribed in clear at compile time.
I looked for packers, but it's not the best solution (PECompact can be detected as a false positive malware, UPX is too easy to de-UPX, ...). I would prefer an idea in my internal code...
Someone would put me on the right way.
A very simple method is to store the strings obfuscated by the ROT13 method.
procedure ROT13(var Str: string);
const
OrdBigA = Ord('A');
OrdBigZ = Ord('Z');
OrdSmlA = Ord('a');
OrdSmlZ = Ord('z');
var
i, o: integer;
begin
for i := 1 to length(Str) do
begin
o := Ord(Str[i]);
if InRange(o, OrdBigA, OrdBigZ) then
Str[i] := Chr(OrdBigA + (o - OrdBigA + 13) mod 26)
else if InRange(o, OrdSmlA, OrdSmlZ) then
Str[i] := Chr(OrdSmlA + (o - OrdSmlA + 13) mod 26);
end;
end;
function ROT13fun(const Str: string): string;
begin
result := Str;
ROT13(result);
end;
const
ObfuscatedString = 'Guvf vf n frperg zrffntr.';
procedure TForm4.FormCreate(Sender: TObject);
begin
ShowMessage(ROT13fun(ObfuscatedString));
end;
Slightly more sophisticated would be to employ the Caesar chipher or the Vigenère chipher.
To obtain the obfuscated strings to use in the source code, you can use a decent text editor like my own Rejbrand Text Editor or Wolfram|Alpha.
Update
ROT13 is very easy to decipher, but it might be more than enough for your situation, depending on how it looks! At least it will become very hard to identify strings in the binary. It will take some real effort to obtain the strings. (After all, the every-day user don't even look at binaries in a hex editor/text editor!) The Caesar cipher is a very simple generalisation of the ROT13 cipher, and is also easily deciphered. Indeed, there are only 25 different 'passwords'. The Vigenère cipher is far trickier, and takes some really serious effort to crack (especially since you don't know precisely where in the binary the strings are).
As an example, below I give a string obfuscated using the Vigenère cihper:
Xlc tsrgcdk sj ‘vrivem’ mw cei sd kli acirivqhfriw cw qsbsir tfmjmgw, rrh biimrk hyi pygk gilhlvc mf ws, wk leq rpws pvgsqc fj agrvwtvcou mrrsiiwx we izcfp-hew cmji, rpxlmixl ml r piqg xigfbzgep zrrkyyuv. Mlrvih, hyi qmrvvr qctmixw vbtpmwkw ilsikc qclvgiq ks wsqy er soxirr klex hyi ilhzvi cbmmvslavrx mt xli Srvxl wj irboekivcr. Mr hymw qstxmsl, ai uwcp mljvwxmeoki xfs tlcqwtep zojmw mt xli seivkw tsrgcdk.
It would certainly be possible to extend the cipher to also take care of digits and special characters, including spaces. It could also be made to mix capitals and small letters. Then it would be terribly hard (although possible) to decipher. It is probably far easier to decipher if the password is a known word, which can be found in the dictionary. If it is not a word, it will be safer.
The text above is obfuscated using a word that you can find in a large-enough dictionary. The text below is obfuscated using a nonsense string as password:
Miwzvjfy m vjsy-tombox zguol ap ahqovz d uwk sbze w conz pe biusvth pagh h njsx. Io puvyeq, fl cjsx xic vmovdq zappzjvz, vnjnatl frcb vy dtmd vhxkt fto babtf davf. Uuxlhqb, khk aa dbn eumsuzq, auk saed vlpnbuuo ywlemz ue pnyl ttmxv. Pa ghof, fl cjsx kmbbzk atmd wv sfjtmxcl rtfysk cb yuta md jsy. Sqf nql njsx ly vs ilusrn o gok uxwupagupaz u.
And, finally, the text below is obfuscated the same way, but - in addition - all spaces and special characters have been removed from the string:
cishkclruervutzgnyarkgzjsaqgsrzvmmrzweolpcnvbkxrvdnqrlurhpmhfaxsuoqncxgzqegnqmngaryfbgozpcgrkgzrrybybmouyzbbkoucbnrnsxkmcbywpllxhkoobmzoydrfvrkhpvsavmzocwjflouboymlotjcnqrirgucdrftllladcwtmnkqehjpmnafoobyvkvdaancbzeokdnsotkkawvanjkryculluyaoklpnojfnqrlatypznpalzocjunuxzdbnzntpqulplekxhrshpttjqyculkkjyxhxgxdozruwlbtkyrsuumkgslbyunabbkryfupvnafobhuoyyvqjlzgzpomc
I challenge you to decipher these three texts. If anyone would succeed in deciphering the last one, I promise to give this person 100 SEK (100 Swedish kronor)!
But, still, Warren P is right: If you really require high security, that even the experts will not be able to decipher, then you should go for some real encryption.
Update
As requested by Warren P, I use the following code to encrypt/decrypt Vigenère:
const
OrdBigA = Ord('A');
OrdBigZ = Ord('Z');
OrdSmlA = Ord('a');
OrdSmlZ = Ord('z');
function imod(const x: integer; const y: integer): integer;
begin
if x >= 0 then
imod := x - floor(x/y) * y
else
imod := x + ceil(-x/y) * y;
end;
procedure Vigenère(var Str: string; const Key: string);
var
n, i, o: integer;
KeyChrs: TBytes;
begin
n := length(Key);
SetLength(KeyChrs, n);
for i := 1 to n do
if InRange(ord(Key[i]), OrdBigA, OrdBigZ) then
KeyChrs[i - 1] := Ord(Key[i]) - OrdBigA
else
raise Exception.Create('Invalid character in Vigenère key.');
for i := 1 to length(Str) do
begin
o := Ord(Str[i]);
if InRange(o, OrdBigA, OrdBigZ) then
Str[i] := Chr(OrdBigA + imod((o - OrdBigA + KeyChrs[(i-1) mod n]), 26))
else if InRange(o, OrdSmlA, OrdSmlZ) then
Str[i] := Chr(OrdSmlA + imod((o - OrdSmlA + KeyChrs[(i-1) mod n]), 26));
end;
end;
function Vigenèref(const Str: string; const Key: string): string;
begin
result := Str;
Vigenère(result, Key);
end;
procedure VigenèreD(var Str: string; const Key: string);
var
n, i, o: integer;
KeyChrs: TBytes;
begin
n := length(Key);
SetLength(KeyChrs, n);
for i := 1 to n do
if InRange(ord(Key[i]), OrdBigA, OrdBigZ) then
KeyChrs[i - 1] := Ord(Key[i]) - OrdBigA
else
raise Exception.Create('Invalid character in Vigenère key.');
for i := 1 to length(Str) do
begin
o := Ord(Str[i]);
if InRange(o, OrdBigA, OrdBigZ) then
Str[i] := Chr(OrdBigA + imod((o - OrdBigA - KeyChrs[(i-1) mod n]), 26))
else if InRange(o, OrdSmlA, OrdSmlZ) then
Str[i] := Chr(OrdSmlA + imod((o - OrdSmlA - KeyChrs[(i-1) mod n]), 26));
end;
end;
function VigenèreDf(const Str: string; const Key: string): string;
begin
result := Str;
VigenèreD(result, Key);
end;
You could use a real encryption library like in this question. A small external utility could take your original string and convert it to a static array of bytes, which would be compiled into your app, and be decrypted and restored in memory as a string. This would have the additional benefit that it would not still look like ascii (range 32..127) and would not be quite so obvious to casual inspectors using a hex editor.
Also, real encryption (even 3DES or Blowfish) would not be so easily removed without even needing to look at your source code or reverse engineer your binaries, as ROT13 or a single level of caesar cypher would be, but then, if your key (used to decrypt/encrypt) is itself not protected, it's not so secure as you might have hoped, either. It would be pretty easy for me to attach a debugger to your code, even the release version, and recover and log all strings in the string heap, at runtime, without even bothering to crack your encryption, even when you use a real library as above. I agree with Andreas that Vigenere seems a reasonable amount of protection and effort for your purposes, and I think ROT13 and a single-level caesar cipher are kind of laughable on their own. Update: The vignere as posted by Andreas is brilliant, though, and I prefer it to a big fat external library, in your case.
For your particular case, which is storing something in a text file, I would have written a small utility that could encrypt and encode your secrets into your source code, and stored the key at least somewhere else. That's like keeping your ammunition in a lockbox, and keeping the key for it somewhere else. Even that is not perfect, but its probably better than ROT13, which is kind of the most "toy" of all the toy encryption styles.
I can't find this anywhere in the Domino Designer help. It seems so straightforward!
All I need to do is find the position of a character in a string.
You could use #Left or #Leftback. I think in this case they work the same.
src:= {your field value to search};
char:= {your target character};
indexof:= #Length(#Left(src;char))
searchResult:=#Left(SearchString;"C");
indexOf:=#If(searchResult="";0;#Length(searchResult));
indexOf
(edited) Please see the answer from charles ross instead.
https://stackoverflow.com/a/19437044/11293
My less efficient method is below.
If you really need the character position though you could do this:
REM {
S Source string
F Character to find
R Location of character in string or 0
};
S := "My string";
F := "t";
LEN_S := #Length(S);
R := 0;
#For(I := 1; I < LEN_S; I := I + 1;
#If(#Middle(S; I; 1) = F;
#Do(R := I; I := LEN_S);
#Nothing
)
);
#Length(src) - #Length(#ReplaceSubstring(src;srch;""))