summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErich Eckner <git@eckner.net>2016-12-19 18:08:17 +0100
committerErich Eckner <git@eckner.net>2016-12-19 18:08:17 +0100
commitcb7c5c51ca22fdb7eab50b76550b2e6005965b2f (patch)
tree1decd6281d843c4cf892ffff6a7a120a4efdd2a1
parente75d61df84dc920f5e460cf56127b51e777559ca (diff)
downloadAnalyzer-cb7c5c51ca22fdb7eab50b76550b2e6005965b2f.tar.xz
wieder was gemacht
-rw-r--r--analyzer.lpi6
-rw-r--r--analyzer.lpr252
-rw-r--r--analyzer.lps152
-rw-r--r--valuesunit.pas236
4 files changed, 570 insertions, 76 deletions
diff --git a/analyzer.lpi b/analyzer.lpi
index f5eae51..4961aad 100644
--- a/analyzer.lpi
+++ b/analyzer.lpi
@@ -29,11 +29,15 @@
<FormatVersion Value="1"/>
</local>
</RunParams>
- <Units Count="1">
+ <Units Count="2">
<Unit0>
<Filename Value="analyzer.lpr"/>
<IsPartOfProject Value="True"/>
</Unit0>
+ <Unit1>
+ <Filename Value="valuesunit.pas"/>
+ <IsPartOfProject Value="True"/>
+ </Unit1>
</Units>
</ProjectOptions>
<CompilerOptions>
diff --git a/analyzer.lpr b/analyzer.lpr
index 348518c..5b6d150 100644
--- a/analyzer.lpr
+++ b/analyzer.lpr
@@ -6,22 +6,33 @@ uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
- classes, sysUtils, custApp
- { you can add units after this };
+ classes, sysUtils, custApp, valuesunit, lowlevelunit, dateutils;
type
- tOption = (oHelp, oInput);
+ tOption = (oHelp, oAcceleration, oPosition, oOutput);
+
+ tOptionMeta = record
+ long: string;
+ short: char;
+ value: byte; // bit 0: kann Wert haben; bit 1: muss Wert haben
+ end;
+
+ tOptionContent = record
+ typ: tOption;
+ hasValue: boolean;
+ value: string;
+ end;
{ TAnalyzer }
tAnalyzer = class(tCustomApplication)
protected
- options: array of tOption;
- oValues: array of string;
+ options: array of tOptionContent;
+ oCnt: array[tOption] of longint;
procedure doRun; override;
procedure parseOptions;
- procedure illegalOption(i: longint);
+ function optionArgument(o: tOption; i: longint): string;
public
constructor create(theOwner: tComponent); override;
destructor destroy; override;
@@ -29,46 +40,70 @@ type
end;
const
- shortOptions: array[tOption] of char =
- ('h','i');
- longOptions: array[tOption] of string = (
- 'help',
- 'input'
- );
- optionValue: array[tOption] of byte = ( // bit 0: kann Wert haben; bit 1: muss Wert haben
- 0,
- 3
+ optionsMeta: array[tOption] of tOptionMeta = (
+ (long: 'help'; short: 'h'; value: $00),
+ (long: 'acceleration'; short: 'a'; value: $03),
+ (long: 'position'; short: 'p'; value: $03),
+ (long: 'output'; short: 'o'; value: $03)
);
{ TAnalyzer }
procedure tAnalyzer.doRun;
var
- errorMsg: string;
+ i: longint;
+ values: array of array[boolean] of tValues;
begin
- // quick check parameters
- errorMsg:=checkOptions('hi:', 'help input:');
- if errorMsg<>'' then begin
- showException(Exception.Create(ErrorMsg));
+ if oCnt[oHelp]>0 then begin
+ writeHelp;
+ terminate;
+ exit;
+ end;
+
+ if oCnt[oAcceleration]=0 then begin
+ writeln('error: required option ''-a'' not given');
+ writeHelp;
halt(1);
end;
- // parse parameters
- if hasOption('h', 'help') then begin
+ if oCnt[oAcceleration]<>oCnt[oPosition] then begin
+ writeln('error: option ''-p'' not given equally often as option ''-a''');
writeHelp;
- terminate;
- exit;
+ halt(1);
end;
- if not hasOption('i','input') then begin
- writeln('error: required option ''-i'' not given');
+ if oCnt[oOutput]<>1 then begin
+ writeln('error: required option ''-o'' not given exactly once');
writeHelp;
halt(1);
end;
+ for i:=0 to oCnt[oAcceleration]-1 do begin
+ if not fileexists(optionArgument(oAcceleration,i)) then begin
+ writeln('Acceleration file '''+optionArgument(oAcceleration,i)+''' does not exist');
+ halt(1);
+ end;
+ if not fileexists(optionArgument(oPosition,i)) then begin
+ writeln('Position file '''+optionArgument(oPosition,i)+''' does not exist');
+ halt(1);
+ end;
+ end;
+
{ add your program here }
+ setlength(values,oCnt[oAcceleration]);
+ for i:=0 to length(values)-1 do begin
+ values[i,false]:=tValues.create;
+ values[i,false].readFromFile(optionArgument(oAcceleration,i));
+ values[i,true]:=tValues.create;
+ values[i,true].readFromFile(values[i,false].timeInterval,optionArgument(oPosition,i));
+ values[i,false].intersect(values[i,true]);
+ end;
- writeln(''''+getOptionValue('i','input')+'''');
+ for i:=0 to length(values)-1 do begin
+ values[i,false].free;
+ values[i,true].free;
+ end;
+ setlength(values,0);
// stop program loop
terminate;
@@ -76,50 +111,144 @@ end;
procedure tAnalyzer.parseOptions;
var
- i: longint;
- s,t: string;
- o: tOption;
- v,gefunden: boolean;
+ i,j,incre,jncre: longint;
+ s: string;
+ oTypen: array of byte; // 0 = argument; 1 = short option(s); 2 = long option
+ o: tOption;
begin
+ for o:=low(tOption) to high(tOption) do
+ oCnt[o]:=0;
+
+ setlength(oTypen,paramcount);
+ for i:=0 to length(oTypen)-1 do
+ if copy(paramstr(i+1),1,2)='--' then
+ oTypen[i]:=2
+ else if copy(paramstr(i+1),1,1)='-' then
+ oTypen[i]:=1
+ else
+ oTypen[i]:=0;
+
setlength(options,0);
- setlength(oValues,0);
- i:=1;
- while i<=paramcount do begin
- s:=paramstr(i);
- if copy(s,1,1)<>'-' then
- illegalOption(i);
- delete(s,1,1);
- gefunden:=false;
- if copy(s,1,1)='-' then begin // long option
- delete(s,1,1);
- if pos('=',s)>0 then begin
- t:=copy(s,pos('=',s)+1,length(s));
- s:=copy(s,1,pos('=',s)-1);
- v:=true;
- end
- else begin
- t:='';
- v:=false;
+ i:=0;
+ while i<length(oTypen) do begin
+ incre:=1;
+ s:=paramstr(i+1);
+ case oTypen[i] of
+ 0: begin
+ writeln('Spurious argument '''+s+''' at position '+inttostr(i+1));
+ halt(1);
+ end;
+ 1: begin
+ delete(s,1,1);
+
+ j:=1;
+ while j<=length(s) do begin
+ jncre:=1;
+ setlength(options,length(options)+1);
+ options[length(options)-1].hasValue:=false;
+ options[length(options)-1].value:='';
+ options[length(options)-1].typ:=low(optionsMeta);
+ while options[length(options)-1].typ<high(optionsMeta) do begin
+ if (optionsMeta[options[length(options)-1].typ].short=s[j]) then
+ break;
+ inc(options[length(options)-1].typ);
+ end;
+ if (optionsMeta[options[length(options)-1].typ].short<>s[j]) then begin
+ writeln('Illegal option at position '+inttostr(i+1)+', character '+inttostr(j)+': '''+s[j]+'''');
+ writeHelp;
+ halt(1);
+ end;
+
+ if odd(optionsMeta[options[length(options)-1].typ].value) // may have value
+ and (((i<length(oTypen)-1) and (oTypen[i+1]=0)) or (j<length(s))) then begin // still arguments left
+ options[length(options)-1].hasValue:=true;
+ if j<length(s) then begin
+ options[length(options)-1].value:=copy(s,j+1,length(s));
+ jncre:=length(s);
+ end
+ else begin
+ options[length(options)-1].value:=paramstr(i+2);
+ inc(incre);
+ end;
+ end
+ else
+ options[length(options)-1].hasValue:=false;
+
+ if (not options[length(options)-1].hasValue) and odd(optionsMeta[options[length(options)-1].typ].value shr 1) then begin
+ writeln('Option '''+optionsMeta[options[length(options)-1].typ].short+''' at position '+inttostr(i+1)+', character '+inttostr(j)+' requires an argument!');
+ writeHelp;
+ halt(1);
+ end;
+ inc(oCnt[options[length(options)-1].typ]);
+ inc(j,jncre);
+ end;
end;
- for o:=low(longOptions) to high(longOptions) do
- if (longOptions[o]<>'') and (longOptions[o]=s) and ((not v) or odd(optionValue[o])) then begin
- gefunden:=true;
- break;
+ 2: begin
+ delete(s,1,2);
+
+ setlength(options,length(options)+1);
+
+ if pos('=',s)>0 then begin
+ options[length(options)-1].value:=copy(s,pos('=',s)+1,length(s));
+ s:=copy(s,1,pos('=',s)-1);
+ options[length(options)-1].hasValue:=true;
+ end
+ else begin
+ options[length(options)-1].value:='';
+ options[length(options)-1].hasValue:=false;
+ end;
+ options[length(options)-1].typ:=low(optionsMeta);
+ while options[length(options)-1].typ<high(optionsMeta) do begin
+ if (optionsMeta[options[length(options)-1].typ].long<>'') and (optionsMeta[options[length(options)-1].typ].long=s) then
+ break;
+ inc(options[length(options)-1].typ);
+ end;
+ if (optionsMeta[options[length(options)-1].typ].long='') or (optionsMeta[options[length(options)-1].typ].long<>s) then begin
+ writeln('Illegal option at position '+inttostr(i+1)+': '''+s+'''');
+ writeHelp;
+ halt(1);
end;
- end;
- if not gefunden then
- illegalOption(i);
+ if (not options[length(options)-1].hasValue) // no value yet
+ and odd(optionsMeta[options[length(options)-1].typ].value) // may have value
+ and (i<length(oTypen)-1) // still arguments left
+ and (oTypen[i+1]=0) then begin // next argument is no option
+ options[length(options)-1].hasValue:=true;
+ options[length(options)-1].value:=paramstr(i+2);
+ inc(incre);
+ end;
+
+ if options[length(options)-1].hasValue and not odd(optionsMeta[options[length(options)-1].typ].value) then begin
+ writeln('Option '''+optionsMeta[options[length(options)-1].typ].long+''' at position '+inttostr(i+1)+' does not take an argument!');
+ writeHelp;
+ halt(1);
+ end;
- inc(i);
+ if (not options[length(options)-1].hasValue) and odd(optionsMeta[options[length(options)-1].typ].value shr 1) then begin
+ writeln('Option '''+optionsMeta[options[length(options)-1].typ].long+''' at position '+inttostr(i+1)+' requires an argument!');
+ writeHelp;
+ halt(1);
+ end;
+ inc(oCnt[options[length(options)-1].typ]);
+ end;
+ end{of case};
+ inc(i,incre);
end;
end;
-procedure tAnalyzer.illegalOption(i: longint);
+function tAnalyzer.optionArgument(o: tOption; i: longint): string;
+var
+ j: longint;
begin
- writeln('Illegal option at position '+inttostr(i)+': '''+paramstr(i)+'''');
- writeHelp;
- halt(1);
+ for j:=0 to length(options)-1 do
+ if (options[j].typ=o) and options[j].hasValue then begin
+ dec(i);
+ if i<0 then begin
+ result:=options[j].value;
+ exit;
+ end;
+ end;
+ raise exception.create('Option '''+optionsMeta[o].long+''' not available '+inttostr(i+1)+' times');
end;
constructor tAnalyzer.create(theOwner: tComponent);
@@ -138,6 +267,7 @@ procedure tAnalyzer.writeHelp;
begin
{ add your help code here }
writeln('usage: ', exeName, ' -h');
+ writeln('usage: ', exeName, ' -i input1 -i input2 -o output');
end;
var
diff --git a/analyzer.lps b/analyzer.lps
index 2f4a0df..e39f80b 100644
--- a/analyzer.lps
+++ b/analyzer.lps
@@ -3,14 +3,13 @@
<ProjectSession>
<Version Value="9"/>
<BuildModes Active="Default"/>
- <Units Count="2">
+ <Units Count="5">
<Unit0>
<Filename Value="analyzer.lpr"/>
<IsPartOfProject Value="True"/>
- <IsVisibleTab Value="True"/>
- <TopLine Value="23"/>
- <CursorPos Y="52"/>
- <UsageCount Value="20"/>
+ <TopLine Value="75"/>
+ <CursorPos X="47" Y="99"/>
+ <UsageCount Value="30"/>
<Loaded Value="True"/>
</Unit0>
<Unit1>
@@ -19,26 +18,151 @@
<EditorIndex Value="-1"/>
<TopLine Value="348"/>
<CursorPos X="44" Y="351"/>
- <UsageCount Value="10"/>
+ <UsageCount Value="9"/>
</Unit1>
+ <Unit2>
+ <Filename Value="optionunit.pas"/>
+ <EditorIndex Value="-1"/>
+ <UsageCount Value="19"/>
+ </Unit2>
+ <Unit3>
+ <Filename Value="valuesunit.pas"/>
+ <IsPartOfProject Value="True"/>
+ <IsVisibleTab Value="True"/>
+ <EditorIndex Value="1"/>
+ <TopLine Value="151"/>
+ <CursorPos X="6" Y="180"/>
+ <UsageCount Value="28"/>
+ <Loaded Value="True"/>
+ </Unit3>
+ <Unit4>
+ <Filename Value="../units/mystringlistunit.pas"/>
+ <EditorIndex Value="-1"/>
+ <TopLine Value="35"/>
+ <CursorPos X="7" Y="52"/>
+ <UsageCount Value="9"/>
+ </Unit4>
</Units>
- <JumpHistory Count="4" HistoryIndex="3">
+ <JumpHistory Count="30" HistoryIndex="29">
<Position1>
- <Filename Value="analyzer.lpr"/>
- <Caret Line="51" Column="50" TopLine="29"/>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="8" Column="34" TopLine="2"/>
</Position1>
<Position2>
- <Filename Value="analyzer.lpr"/>
- <Caret Line="52" Column="15" TopLine="30"/>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="92" TopLine="68"/>
</Position2>
<Position3>
<Filename Value="analyzer.lpr"/>
- <Caret Line="53" Column="39" TopLine="30"/>
+ <Caret Line="99" Column="61" TopLine="78"/>
</Position3>
<Position4>
- <Filename Value="analyzer.lpr"/>
- <Caret Line="52" Column="38" TopLine="30"/>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="91" Column="52" TopLine="73"/>
</Position4>
+ <Position5>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="22" Column="28"/>
+ </Position5>
+ <Position6>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="23" Column="36"/>
+ </Position6>
+ <Position7>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="94" Column="40" TopLine="70"/>
+ </Position7>
+ <Position8>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="102" TopLine="72"/>
+ </Position8>
+ <Position9>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="24" Column="72"/>
+ </Position9>
+ <Position10>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="95" Column="34" TopLine="73"/>
+ </Position10>
+ <Position11>
+ <Filename Value="analyzer.lpr"/>
+ <Caret Line="98" Column="40" TopLine="77"/>
+ </Position11>
+ <Position12>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="12" Column="16" TopLine="52"/>
+ </Position12>
+ <Position13>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="57" Column="15" TopLine="49"/>
+ </Position13>
+ <Position14>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="58" Column="15" TopLine="49"/>
+ </Position14>
+ <Position15>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="59" Column="15" TopLine="49"/>
+ </Position15>
+ <Position16>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="62" Column="15" TopLine="49"/>
+ </Position16>
+ <Position17>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="63" Column="15" TopLine="49"/>
+ </Position17>
+ <Position18>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="64" Column="15" TopLine="49"/>
+ </Position18>
+ <Position19>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="110" Column="21" TopLine="95"/>
+ </Position19>
+ <Position20>
+ <Filename Value="valuesunit.pas"/>
+ </Position20>
+ <Position21>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="25" Column="26"/>
+ </Position21>
+ <Position22>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="69" Column="21" TopLine="45"/>
+ </Position22>
+ <Position23>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="212" Column="30" TopLine="176"/>
+ </Position23>
+ <Position24>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="38"/>
+ </Position24>
+ <Position25>
+ <Filename Value="analyzer.lpr"/>
+ <Caret Line="58" Column="3" TopLine="46"/>
+ </Position25>
+ <Position26>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="226" Column="67" TopLine="187"/>
+ </Position26>
+ <Position27>
+ <Filename Value="valuesunit.pas"/>
+ <Caret Line="47" Column="30" TopLine="22"/>
+ </Position27>
+ <Position28>
+ <Filename Value="analyzer.lpr"/>
+ <Caret Line="47" Column="30" TopLine="33"/>
+ </Position28>
+ <Position29>
+ <Filename Value="analyzer.lpr"/>
+ <Caret Line="97" Column="98" TopLine="66"/>
+ </Position29>
+ <Position30>
+ <Filename Value="analyzer.lpr"/>
+ <Caret Line="9" Column="66" TopLine="3"/>
+ </Position30>
</JumpHistory>
</ProjectSession>
</CONFIG>
diff --git a/valuesunit.pas b/valuesunit.pas
new file mode 100644
index 0000000..97d960f
--- /dev/null
+++ b/valuesunit.pas
@@ -0,0 +1,236 @@
+unit valuesunit;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, lowlevelunit;
+
+type
+ tWert = record
+ time: int64; // unix timestamp * 1000
+ vec: array['x'..'z'] of extended;
+ end;
+
+ tValues = class
+ private
+ werte: array of tWert;
+ public
+ constructor create;
+ destructor destroy; override;
+ procedure readFromFile(dat: string); overload;
+ procedure readFromFile(ti: tExtPoint; dat: string); overload;
+ procedure readFromFile(minT,maxT: extended; dat: string); overload;
+ function count: int64;
+ function timeInterval: tExtPoint;
+ procedure intersect(v: tValues);
+ end;
+
+function interpolate(w1,w2: tWert; x: extended): tWert; inline;
+function isoStrToDateTime(s: string): extended; inline;
+function timeToInt64(s: string): int64;
+
+implementation
+
+uses
+ math, dateutils;
+
+constructor tValues.create;
+begin
+ inherited create;
+ setlength(werte,0);
+end;
+
+destructor tValues.destroy;
+begin
+ setlength(werte,0);
+ inherited destroy;
+end;
+
+procedure tValues.readFromFile(dat: string);
+begin
+ readFromFile(-infinity,infinity,dat);
+end;
+
+procedure tValues.readFromFile(ti: tExtPoint; dat: string);
+begin
+ readFromFile(ti['x'],ti['y'],dat);
+end;
+
+procedure tValues.readFromFile(minT,maxT: extended; dat: string);
+var
+ f: textfile;
+ s: string;
+ i,delta,cnt: int64;
+ ws: tWert;
+ c: char;
+ isXml: boolean;
+begin
+ setlength(werte,0);
+ fillchar(ws,sizeOf(tWert),0);
+ cnt:=0;
+ assignFile(f,dat);
+ reset(f);
+ isXml:=false;
+ s:='';
+ while (s<>'') or not eof(f) do begin
+ if s='' then
+ readln(f,s);
+ if s='' then
+ continue;
+
+ if (not isXml) and (not (s[1] in ['0'..'9'])) then begin
+ if copy(s,1,6)='<?xml ' then
+ isXml:=true
+ else begin
+ s:='';
+ continue;
+ end;
+ end;
+
+ if isXml then begin
+ if pos('<trkpt lat="',s)=0 then begin
+ s:='';
+ continue;
+ end;
+
+ delete(s,1,pos('<trkpt lat="',s));
+ delete(s,1,pos('"',s));
+ ws.vec['y']:=strtofloat(erstesArgument(s,'" '));
+ if pos('lon="',s)<>1 then
+ raise exception.create('Syntax error in '''+dat+''' (lon) - no valid gpx file.'#10'Hickup: '''+copy(s,1,40)+' ...''');
+ delete(s,1,pos('"',s));
+ ws.vec['x']:=strtofloat(erstesArgument(s,'"'));
+ if pos('><ele>',s)<>1 then
+ raise exception.create('Syntax error in '''+dat+''' (lat) - no valid gpx file.'#10'Hickup: '''+copy(s,1,40)+' ...''');
+ delete(s,1,pos('>',s));
+ delete(s,1,pos('>',s));
+ ws.vec['z']:=strtofloat(erstesArgument(s,'<'));
+ if pos('/ele><time>',s)<>1 then
+ raise exception.create('Syntax error in '''+dat+''' (ele) - no valid gpx file.'#10'Hickup: '''+copy(s,1,40)+' ...''');
+ delete(s,1,pos('>',s));
+ delete(s,1,pos('>',s));
+ ws.time:=timeToInt64(erstesArgument(s,'<'));
+ if pos('/time>',s)<>1 then
+ raise exception.create('Syntax error in '''+dat+''' (time) - no valid gpx file.'#10'Hickup: '''+copy(s,1,40)+' ...''');
+ end
+ else begin
+ ws.time:=strtoint64(erstesArgument(s,';'));
+ erstesArgument(s,';');
+ for c:='x' to 'z' do
+ ws.vec[c]:=strtofloat(erstesArgument(s,';'));
+ s:='';
+ end;
+
+ if cnt>0 then
+ delta:=ws.time-werte[cnt-1].time
+ else
+ delta:=1;
+
+ cnt:=cnt+delta;
+ if cnt>=length(werte) then
+ setlength(werte,cnt+64*1024);
+ if cnt>=length(werte) then
+ raise exception.create('Failed to enlarge array.');
+
+ if delta=1 then
+ move(ws,werte[cnt-1],sizeOf(tWert))
+ else
+ for i:=delta-1 downto 0 do
+ werte[cnt-i-1]:=
+ interpolate(
+ werte[cnt-delta-1],
+ ws,
+ (delta-i)/delta
+ );
+
+ if werte[0].time<minT then begin
+ delta:=cnt-1;
+ while (werte[delta].time>=minT) and (delta>0) do
+ dec(delta);
+ for i:=delta to cnt-1 do
+ move(werte[i],werte[i-delta],sizeOf(tWert));
+ cnt:=cnt-delta;
+ end;
+
+ if werte[cnt-1].time>maxT then begin
+ while (cnt>0) and (werte[cnt-2].time>maxT) do
+ dec(cnt);
+ break;
+ end;
+ end;
+ closeFile(f);
+ setlength(werte,cnt);
+end;
+
+function tValues.count: int64;
+begin
+ result:=length(werte);
+end;
+
+function tValues.timeInterval: tExtPoint;
+begin
+ result['x']:=werte[0].time;
+ result['y']:=werte[count-1].time;
+end;
+
+procedure tValues.intersect(v: tValues);
+begin
+ if
+end;
+
+// general functions ***********************************************************
+
+function interpolate(w1,w2: tWert; x: extended): tWert; inline;
+var
+ c: char;
+begin
+ result.time:=
+ round(w1.time*(1-x) + w2.time*x);
+ for c:='x' to 'z' do begin
+ result.vec[c]:=
+ round(w1.vec[c]*(1-x) + w2.vec[c]*x);
+ end;
+end;
+
+function isoStrToDateTime(s: string): extended; inline;
+begin
+ if (length(s)<>19) or
+ (s[5]<>'-') or
+ (s[8]<>'-') or
+ (s[11]<>' ') or
+ (s[14]<>':') or
+ (s[17]<>':') then
+ raise exception.create(''''+s+''' is not a valid iso date-time');
+ result:=
+ encodeDate(
+ strToInt(copy(s,1,4)),
+ strToInt(copy(s,6,2)),
+ strToInt(copy(s,9,2))
+ ) +
+ encodeTime(
+ strToInt(copy(s,12,2)),
+ strToInt(copy(s,15,2)),
+ strToInt(copy(s,18,2)),
+ 0
+ );
+end;
+
+function timeToInt64(s: string): int64;
+begin
+ if (length(s)<>20) or
+ (s[5]<>'-') or
+ (s[8]<>'-') or
+ (s[11]<>'T') or
+ (s[14]<>':') or
+ (s[17]<>':') or
+ (s[20]<>'Z') then
+ raise exception.create(''''+s+''' is not a valid date-time');
+ delete(s,20,1);
+ s[11]:=' ';
+ result:=round(dateTimeToUnix(isoStrToDateTime(s))*1000);
+end;
+
+end.
+