View Issue Details

IDProjectCategoryView StatusLast Update
0035178LazarusTAChartpublic2019-03-03 19:54
ReporterMarcin WiazowskiAssigned Towp 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version2.1 (SVN)Product Build60564 
Target Version2.2Fixed in Version 
Summary0035178: TAChart: streaming issue in TFitSeries
DescriptionThe issue is of same kind as 0035125, so I'll provide only a basic description here.


The attached Reproduce application has two identical charts, with two identical TFitSeries series. I edited LFM file manually, so the behavior is:

Chart1FitSeries:
  FitEquation = feCustom <==== sets ParamCount to default value 3
  ParamCount = 6 <==== sets ParamCount to 6

Chart2FitSeries:
  ParamCount = 6 <==== sets ParamCount to 6
  FitEquation = feCustom <==== sets ParamCount to default value 3

As a consequence, Chart2FitSeries ends up with ParamCount = 3 instead of 6, which raises an exception in FormCreate(), where there is expected that ParamCount is 6.


The attached patch is trivial and solves the problem.
TagsNo tags attached.
Fixed in Revision60566
LazTarget2.2
WidgetsetWin32/Win64
Attached Files
  • Reproduce.zip (2,535 bytes)
  • patch.diff (957 bytes)
    Index: components/tachart/tafuncseries.pas
    ===================================================================
    --- components/tachart/tafuncseries.pas	(revision 60564)
    +++ components/tachart/tafuncseries.pas	(working copy)
    @@ -292,6 +292,7 @@
       TFitSeries = class(TBasicPointSeries)
       strict private
         FAutoFit: Boolean;
    +    FCachedParamCount: Integer;
         FDrawFitRangeOnly: Boolean;
         FFitEquation: TFitEquation;
         FFitParams: TFitParamArray; // raw values, not transformed!
    @@ -2038,6 +2039,7 @@
     procedure TFitSeries.Loaded;
     begin
       inherited;
    +  ParamCount := FCachedParamCount;
       if FAutoFit and (FFitEquation <> feCustom) then ExecFit;
     end;
     
    @@ -2164,6 +2166,7 @@
     
     procedure TFitSeries.SetParamCount(AValue: Integer);
     begin
    +  FCachedParamCount := AValue; // must be assigned here, before the validation!
       if (AValue = ParamCount) or not (FFitEquation in [fePolynomial, feCustom]) then
         exit;
       if AValue <= 0 then
    
    patch.diff (957 bytes)

Activities

Marcin Wiazowski

2019-03-03 00:48

reporter  

Reproduce.zip (2,535 bytes)

Marcin Wiazowski

2019-03-03 00:49

reporter  

patch.diff (957 bytes)
Index: components/tachart/tafuncseries.pas
===================================================================
--- components/tachart/tafuncseries.pas	(revision 60564)
+++ components/tachart/tafuncseries.pas	(working copy)
@@ -292,6 +292,7 @@
   TFitSeries = class(TBasicPointSeries)
   strict private
     FAutoFit: Boolean;
+    FCachedParamCount: Integer;
     FDrawFitRangeOnly: Boolean;
     FFitEquation: TFitEquation;
     FFitParams: TFitParamArray; // raw values, not transformed!
@@ -2038,6 +2039,7 @@
 procedure TFitSeries.Loaded;
 begin
   inherited;
+  ParamCount := FCachedParamCount;
   if FAutoFit and (FFitEquation <> feCustom) then ExecFit;
 end;
 
@@ -2164,6 +2166,7 @@
 
 procedure TFitSeries.SetParamCount(AValue: Integer);
 begin
+  FCachedParamCount := AValue; // must be assigned here, before the validation!
   if (AValue = ParamCount) or not (FFitEquation in [fePolynomial, feCustom]) then
     exit;
   if AValue <= 0 then
patch.diff (957 bytes)

wp

2019-03-03 01:09

developer   ~0114591

> I edited LFM file manually

Didn't you say recently that anything can happen when this is done?

Marcin Wiazowski

2019-03-03 01:19

reporter   ~0114592

Ok, I haven't explained that. In 0035125 we can read:

Already got an answer from Mattias: "Do not rely on property order! And do not execute properties immediately, e.g. descendant forms may change the properties. Wait with applying properties until Loaded is called."

Instead of using descendant forms or something else, I just changed the order manually to show, that the code currently relies on the property order.

wp

2019-03-03 11:24

developer   ~0114594

(Just a joke..., sorry that I did not make it clear).

The problem is more than streaming. It happens because the setter of TFitSeries.FitEquation always changes the ParamCount to its default when the new FitEquation is feCustom or fePolynomial. But it should change the ParamCount only in the hard-coded polynomial cases, i.e. when FitEquation is feLinear, feExp or fePower. Initialization has been done correctly in the series' constructor, there is not need to use the default value of ParamCount again.

Using

  if not (FFitEquation in [fePolynomial, feCustom]) then
    SetLength(FFitParams, 2)

solves the issue both for streaming and for runtime code having initially FitEquation=fePolynomial, setting the ParamCount and then switching to feCustom.

Marcin Wiazowski

2019-03-03 19:54

reporter   ~0114603

In fact, you fixed the root cause of the problem, which is even better. Thanks!

Issue History

Date Modified Username Field Change
2019-03-03 00:48 Marcin Wiazowski New Issue
2019-03-03 00:48 Marcin Wiazowski File Added: Reproduce.zip
2019-03-03 00:49 Marcin Wiazowski File Added: patch.diff
2019-03-03 01:09 wp Assigned To => wp
2019-03-03 01:09 wp Status new => assigned
2019-03-03 01:09 wp Note Added: 0114591
2019-03-03 01:19 Marcin Wiazowski Note Added: 0114592
2019-03-03 11:24 wp Note Added: 0114594
2019-03-03 11:25 wp Fixed in Revision => 60566
2019-03-03 11:25 wp LazTarget => 2.2
2019-03-03 11:25 wp Status assigned => resolved
2019-03-03 11:25 wp Resolution open => fixed
2019-03-03 11:25 wp Target Version => 2.2
2019-03-03 19:54 Marcin Wiazowski Note Added: 0114603
2019-03-03 19:54 Marcin Wiazowski Status resolved => closed