Compare commits

..

510 Commits

Author SHA1 Message Date
Alejandro Martinez
735ef1ab0c August 2024 Development Build
[publish binaries]
2024-08-02 17:29:27 -03:00
jgpallero
772d30c444 Update Spanish translation (#4528) 2024-08-01 09:58:54 -03:00
Alejandro Martinez
1eb07f968e Update translation files
To match current source code for dev build 2408
2024-07-31 21:08:33 -03:00
Joachim Kohlhammer
ee1be4c48e ActivitySidebar: New action "scroll to current" (#4524)
Activity Sidebar: Added a new action to ride navigators context / burger
menu: "Scroll to current activity"
2024-07-31 11:03:29 -03:00
Joachim Kohlhammer
dc38e4a148 Changed the tab-order in the athlete selector (#4523)
* Changed the traversal order in ChooseCyclistDialog when using the
  tab-key:
  * Before this change:
    List -> New -> Open -> Cancel -> Delete -> List
  * After this change:
    List -> New -> Delete -> Cancel -> Open -> List
* Changed the default button (activated when pressing enter):
  * "New" when no athlete is available
  * "Open" when athletes are available
  * Behaviour before this change: Always "New"
* Removed the parameter allowNew from the constructor
  ChooseCyclistDialog::ChooseCyclistDialog as it was only used with
  the value true
2024-07-31 11:01:28 -03:00
Joachim Kohlhammer
0799c56c2e Fixed compilation error with gcc 14 (#4527)
gcc 14 turned some warnings into errors:
https://gcc.gnu.org/gcc-14/porting_to.html#warnings-as-errors

This commit fixes the error in EzUsb-1.0.c and additionally removes
indentation warnings.
2024-07-31 10:59:48 -03:00
Alejandro Martinez
1728c13186 Update French translation
Contributed by Patrick at the users forum
Fixes #4526
2024-07-29 21:18:55 -03:00
Alejandro Martinez
ed19e76f74 TrainerDay API - add encrypted key and page size
[skip AppVeyor]
Part of #4522
2024-07-29 17:56:30 -03:00
Alejandro Martinez
90cb68623f Fix typo in appveyor.yml
From latest commit
2024-07-25 07:31:12 -03:00
Joachim Kohlhammer
ef716f8568 Added support for the TrainerDay workouts/find API (#4522)
* Added support for the TrainerDay workouts/find API

* Added a new (optional) tab to the TrainerDay workouts download dialog
* Deferring loading of the classic list of workouts until this tab is
  activated
* Implemented the API for TrainerDays /workouts/find (see
  https://api.trainerday.com/api-explorer/)
* Visualizing the workouts using a colored ErgFilePlot
* Modified ErgFilePlot::setData to directly use the data of the given
  ErgFile instead of falling back to the ErgFile set in the context
  (required to display multiple plots at once)
* Added a simplified version of the existing workouts query sytnax
  (supported verbs: duration, dominantzone)
* Saving the workouts as trainerday-<hash>.erg
* Using the segments-section as input for the hash and to identify
  duplicates
* Functionality can be enabled in gcconfig.pri (GC_WANT_TRAINERDAY_API)
* Prepared the travis-scripts before_script.sh to inject the API key to Secrets.h
* Prepared appveyor.yml to inject the API key to Secrets.h
* Patching GC_TRAINERDAY_API_PAGESIZE for appveyor
* Configured api key for TrainerDay in appveyor
2024-07-24 12:01:14 -03:00
Alejandro Martinez
0a8e0b6cc8 Update snapshot builds
Changes from DEV20404
36207bf FIT import - don't use CIQ speed as standard speed
7ea54fa Enable Calendar and Navigator charts for Trends
65945e5 Metadata tile initial creation update fix and time & date field
support (#4518)
65bf2c0 Add tool tips to trainer controls (#4517)
b4eea7f Change SMA smoothing to always include current point
7052724 ErgFileplot: Updating the zone-coloring and prediction on
changed intensity (#4515)
0d78b3e RunMetrics - Fix Efficiency Index
29644fe POSITION - FitFile decoder - Add cyclist position
ad6a0c3 Dialwindow font scaling (v2) (#4511)
fb76896 ErgDB is now TrainerDay
e592645 Fixed crash on startup if no power zones for bikes are defined
(#4509)
2681536 Updated qwt to 6.3 (qwt-multiaxes branch) (#4497)
2b23d6a Fix qt colors passed to GColor macro (#4501)
04f2f70 Change EditNamedSearches parent to MainWindow (Fixes colors on
dark themes)
dc5da99 Remove Frame on Workout Info
7684b4a Remove duplicate theme color code in Pages.cpp (#4503)
9256358 GCColor::readConfig correct name to setting check (#4502)
2ac2cd6 Batch Processing addition metadata update (#4399)
9647975 Fix isSpecial(internalName) in SpecialFields
e41e6b6 Fit: Add FIELD_87 for record (cycle_length16) fix #4489
c088aaf Fixes the background colour of the group by sub menu (#4492)
06a6dbe Fix copy paste error preventing macOS build
5e3db39 Add delete button to manage filters (#4493)
77df5b3 Train View: Improved the selection of workouts (#4400)
cfb8c2f Manage Perspectives - perspectives list cosmetics
f1bb83f Update Images default chart
562ef17 Update Spanish translation (#4487)
57c11e0 Remove Ctrl+A shortcut for Add Cloud Account
cf2e8d8 Enable translation of Save Changes in SaveExitDialog
1b49890 Update German Translation
f97770f GC CSV Export - rcad instead of cad for runs
7a11a6a Initializing AllPlot::isPanning to false (#4482)
76dedfb Fix Average Speed aggregation
6299374 Images chart update on image drop and import
fdb6d17 Python Web Chart - Don't accept drops
68ad048 Update Images Python chart in default layout
2d8bdd7 FitRideFile - Decode GAP extra field in m/s
5073ba8 Add Images chart to default layout
c693ed6 FitRideFile - Extra fields 136, 143 and 144
4f5a0eb CP Chart - show/hide interval settings based on model and
fitting selection (#4382)
0b144cc Train View: Coloring by powerzones in ErgFilePlot (#4479)
02835e3 Added support for old Daum devices before 2001 (#4303)
71c72d6 Changed the standard colors for compare-mode (#4478)
118eafe FitRideFile : A devApp can replace another with same local id
1241c0a Use elapsed time for session (instead of timestamp) fix #4474
a1a76fb WorkoutWizard - Don't save and close on Cancel
64c7ce3 Improved search/filter box drop down menu icon (#4470)
[publish binaries]
2024-07-13 12:33:55 -03:00
Alejandro Martinez
36207bf882 FIT import - don't use CIQ speed as standard speed
Since units not necessarily are the same.
Test file: test/rowing/RowingCIQspeed.fit
2024-07-12 17:58:15 -03:00
Alejandro Martinez
7ea54faafc Enable Calendar and Navigator charts for Trends
Include them in a Diary perspective in default layout.
Since these charts were not deprecated yet, lets make them
accessible until we have a suitable calendar chart replacement.
2024-07-10 19:38:45 -03:00
Paul Johnson
65945e56d9 Metadata tile initial creation update fix and time & date field support (#4518) 2024-07-03 18:43:36 -03:00
Alejandro Martinez
553b9aa378 Fix Snapshot Builds release title
[skip ci]
2024-06-29 10:46:40 -03:00
Alejandro Martinez
3f2ae0ae38 Update snapshot builds
Changes from DEV2404
65bf2c0 Add tool tips to trainer controls (#4517)
b4eea7f Change SMA smoothing to always include current point
7052724 ErgFileplot: Updating the zone-coloring and prediction on changed intensity (#4515)
0d78b3e RunMetrics - Fix Efficiency Index
29644fe POSITION - FitFile decoder - Add cyclist position
ad6a0c3 Dialwindow font scaling (v2) (#4511)
fb76896 ErgDB is now TrainerDay
e592645 Fixed crash on startup if no power zones for bikes are defined (#4509)
2681536 Updated qwt to 6.3 (qwt-multiaxes branch) (#4497)
2b23d6a Fix qt colors passed to GColor macro (#4501)
04f2f70 Change EditNamedSearches parent to MainWindow (Fixes colors on dark themes)
dc5da99 Remove Frame on Workout Info
7684b4a Remove duplicate theme color code in Pages.cpp (#4503)
9256358 GCColor::readConfig correct name to setting check (#4502)
2ac2cd6 Batch Processing addition metadata update (#4399)
9647975 Fix isSpecial(internalName) in SpecialFields
e41e6b6 Fit: Add FIELD_87 for record (cycle_length16) fix #4489
c088aaf Fixes the background colour of the group by sub menu (#4492)
06a6dbe Fix copy paste error preventing macOS build
5e3db39 Add delete button to manage filters (#4493)
77df5b3 Train View: Improved the selection of workouts (#4400)
cfb8c2f Manage Perspectives - perspectives list cosmetics
f1bb83f Update Images default chart
562ef17 Update Spanish translation (#4487)
57c11e0 Remove Ctrl+A shortcut for Add Cloud Account
cf2e8d8 Enable translation of Save Changes in SaveExitDialog
1b49890 Update German Translation
f97770f GC CSV Export - rcad instead of cad for runs
7a11a6a Initializing AllPlot::isPanning to false (#4482)
76dedfb Fix Average Speed aggregation
6299374 Images chart update on image drop and import
fdb6d17 Python Web Chart - Don't accept drops
68ad048 Update Images Python chart in default layout
2d8bdd7 FitRideFile - Decode GAP extra field in m/s
5073ba8 Add Images chart to default layout
c693ed6 FitRideFile - Extra fields 136, 143 and 144
4f5a0eb CP Chart - show/hide interval settings based on model and
fitting selection (#4382)
0b144cc Train View: Coloring by powerzones in ErgFilePlot (#4479)
02835e3 Added support for old Daum devices before 2001 (#4303)
71c72d6 Changed the standard colors for compare-mode (#4478)
118eafe FitRideFile : A devApp can replace another with same local id
1241c0a Use elapsed time for session (instead of timestamp) fix #4474
a1a76fb WorkoutWizard - Don't save and close on Cancel
64c7ce3 Improved search/filter box drop down menu icon (#4470)
[publish binaries]
2024-06-28 16:11:07 -03:00
Nick Hastings
65bf2c00e3 Add tool tips to trainer controls (#4517)
Add a preferences option to enable/disable these tooltips.
Default is enabled. If enabled tooltips will also be shown
for disabled controls in TrainBottom so users can preview
what they do once the session start.
2024-06-27 09:30:41 -03:00
Alejandro Martinez
b4eea7f8fb Change SMA smoothing to always include current point
It is the common practice, and it works that way on forward mode,
but in backward mode current point was excluded from the average.
2024-06-24 11:42:35 -03:00
Joachim Kohlhammer
7052724fe7 ErgFileplot: Updating the zone-coloring and prediction on changed intensity (#4515)
This is a followup to #4479, taking care of manually changed intensity:
* Adjusting the coloring when sections change their power zone
* Adjusting the W'Balance prediction
2024-06-22 10:49:35 -03:00
Alejandro Martinez
0d78b3e9c8 RunMetrics - Fix Efficiency Index
Average Power is based on Time Recording, not Duration,
so the averaging base fixup is changed accordingly.
Aggregation is now based on Time Moving instead on 1,
to account for the relative weight of different runs.
2024-06-21 12:42:42 -03:00
Alejandro Martinez
68e18ae65e Avoid conflicts with min/max macros in windows.h
[skip ci]
It happens building with Qt 6.7.1 using MSVC2019,
workaround from: https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std
2024-06-20 19:38:53 -03:00
Alejandro Martinez
6a88d775b0 Fix previous commit
Commit 29644fe10 fixes #4328, this one makes 2 changes:
1) Delete created XDataPoint when it is not appended to the XDataSeries
   to avoid memory leaks.
2) Remove fake positions since they are nor reported by devices, their
   inference doesn't seem safe and it can be done where it is required.
2024-06-18 19:06:48 -03:00
Vianney BOYER
29644fe102 POSITION - FitFile decoder - Add cyclist position 2024-06-18 18:20:09 -03:00
Joachim Kohlhammer
ad6a0c30e2 Dialwindow font scaling (v2) (#4511)
* DialWindow: Scaling font in both dimensions

Currently the font in DialWindow is only scaled to make the text fit
into the label vertically. This commit scales the font in both
dimensions and prevents cutting off the content.

The font is rescaled
* If the DialWindow itself is resized
* If the text set and is longer than the previous one
* Every 10 text-changes

* Trainmode: Added a global setting to finetune telemetry font scaling

* Added option to Options -> Train -> Preferences for configuring the
  font scaling strategy of Telemetry / DialWindows
  * "Height only" (default, as before)
  * "Height and width"
* Changed the layout of this Page to QFormLayout to match the other
  Pages
2024-06-13 13:11:30 -03:00
Alejandro Martinez
fb768969ee ErgDB is now TrainerDay
Fixes #2963
2024-06-03 17:16:57 -03:00
Joachim Kohlhammer
b581ef83c7 Added screenshots for wiki-documentation (#4510) [skip ci]
5 new screenshots for documenting the workout-selection feature
introduced with #4400
2024-06-01 08:50:39 -03:00
Alejandro Martinez
b0a498f25a Partially revert changes introduced by 1b49890
They were included by accident, sorry.
2024-05-31 16:41:16 -03:00
Joachim Kohlhammer
e592645cfb Fixed crash on startup if no power zones for bikes are defined (#4509)
Fix for #4508:
* Safeguarded reading zones in TrainSidebar.cpp
* Added additional check to prevent PowerZonesWidget from painting itself
  if zone list is empty
* Returning a empty list from multiple methods in class Zones if given
  range is out of allowed range (was: check only for range too high, below
  0 was ignored):
  * Zones::getZoneLows(.)
  * Zones::getZoneHighs(.)
  * Zones::getZoneNames(.)
  * Zones::getZoneDescriptions(.)
2024-05-31 13:59:02 -03:00
Alejandro Martinez
804a9046d9 Bump QWT version
It reports as 6.8 corresponding to 6.3 multiaxis branch
Part of #4497
2024-05-30 19:18:31 -03:00
Joachim Kohlhammer
2681536c68 Updated qwt to 6.3 (qwt-multiaxes branch) (#4497)
Using qwt from https://sourceforge.net/p/qwt/git/ci/qwt-multiaxes/tree/

Applied the following changes to qwt 6.3:
* Added QwtZone to qwt_plot_curve.cpp
* Disabled the emitting of Layout Requests on geometry changes of
  QwtScaleWidget - without this, CPU utilization was up to 100% on
  one core

Fixes #4495
2024-05-30 15:32:43 -03:00
Paul Johnson
2b23d6adf0 Fix qt colors passed to GColor macro (#4501) 2024-05-30 09:25:14 -03:00
Alejandro Martinez
04f2f70dbd Change EditNamedSearches parent to MainWindow
This overrides the previous commit (7c74faf)
Using context->mainWindow is more explicit,
and likely more robust.
2024-05-29 19:08:20 -03:00
Alejandro Martinez
7c74fafc4a Change EditNamedSearches parent to MainWindow
So colors match other dialogs avoiding legibility issues on dark themes.
This change doesn't seem to have negative side effects testing on
Windows, macOS and Linux (Ubuntu 22.04 over WSL) but on Linux it may
dependend on the windows manager. We can revert later otherwise.
Fixes #4506
Fixes #4504
2024-05-29 16:17:58 -03:00
Mark Liversedge
dc5da99cbc Remove Frame on Workout Info
.. workout info pane in train view has a frame which is jarring
   when compared to all the other sidebar items
2024-05-28 09:48:42 +01:00
Paul Johnson
7684b4a39b Remove duplicate theme color code in Pages.cpp (#4503)
Refactored into GColor::getThemeColor for easier manteinance.
2024-05-27 18:53:39 -03:00
Paul Johnson
9256358756 GCColor::readConfig correct name to setting check (#4502) 2024-05-26 19:30:16 -03:00
Alejandro Martinez
7cfd1fc79d Fix Uploding to snapshot release
[skip AppVeyor]
[skip osx]
Continuation of 7f3b3d2c1b
[publish binaries]
2024-05-26 09:20:23 -03:00
Alejandro Martinez
74afb03fee Update Snapshot Builds
2ac2cd6 Batch Processing addition metadata update (#4399)
9647975 Fix isSpecial(internalName) in SpecialFields
e41e6b6 Fit: Add FIELD_87 for record (cycle_length16) fix #4489
c088aaf Fixes the background colour of the group by sub menu (#4492)
06a6dbe Fix copy paste error preventing macOS build
5e3db39 Add delete button to manage filters (#4493)
77df5b3 Train View: Improved the selection of workouts (#4400)
cfb8c2f Manage Perspectives - perspectives list cosmetics
f1bb83f Update Images default chart
562ef17 Update Spanish translation (#4487)
57c11e0 Remove Ctrl+A shortcut for Add Cloud Account
cf2e8d8 Enable translation of Save Changes in SaveExitDialog
1b49890 Update German Translation
f97770f GC CSV Export - rcad instead of cad for runs
7a11a6a Initializing AllPlot::isPanning to false (#4482)
76dedfb Fix Average Speed aggregation
6299374 Images chart update on image drop and import
fdb6d17 Python Web Chart - Don't accept drops
68ad048 Update Images Python chart in default layout
2d8bdd7 FitRideFile - Decode GAP extra field in m/s
5073ba8 Add Images chart to default layout
c693ed6 FitRideFile - Extra fields 136, 143 and 144
4f5a0eb CP Chart - show/hide interval settings based on model and
fitting selection (#4382)
0b144cc Train View: Coloring by powerzones in ErgFilePlot (#4479)
02835e3 Added support for old Daum devices before 2001 (#4303)
71c72d6 Changed the standard colors for compare-mode (#4478)
118eafe FitRideFile : A devApp can replace another with same local id
1241c0a Use elapsed time for session (instead of timestamp) fix #4474
a1a76fb WorkoutWizard - Don't save and close on Cancel
64c7ce3 Improved search/filter box drop down menu icon (#4470)
[publish binaries]
2024-05-25 21:14:43 -03:00
Alejandro Martinez
7f3b3d2c1b Upload builds to snapshot GitHub release
[skip ci]
Fixes #4490
2024-05-25 21:04:45 -03:00
Alejandro Martinez
266b119055 Replace defunt keep.sh by temp.sh for artifacts upload
[skip AppVeyor]
2024-05-25 11:42:04 -03:00
Paul Johnson
2ac2cd66a1 Batch Processing addition metadata update (#4399) 2024-05-24 10:40:44 -03:00
Paul Johnson
889b1894c5 Fixes build error at VideoWindow line 403 (#4500)
Introduced by 77df5b372c
2024-05-23 21:39:27 -03:00
Alejandro Martinez
9647975643 Fix isSpecial(internalName) in SpecialFields
So we can find fields which cannot be updated
in the normal way.
2024-05-23 20:25:19 -03:00
grauser
e41e6b6e88 Fit: Add FIELD_87 for record (cycle_length16)
fix #4489
2024-05-23 22:47:47 +02:00
Paul Johnson
c088aafb5c Fixes the background colour of the group by sub menu (#4492) 2024-05-22 20:06:38 -03:00
Alejandro Martinez
06a6dbed07 Fix copy paste error preventing macOS build
Introduced by 77df5b372c
2024-05-22 19:58:32 -03:00
Paul Johnson
5e3db39a49 Add delete button to manage filters (#4493) 2024-05-22 10:51:10 -03:00
Joachim Kohlhammer
77df5b372c Train View: Improved the selection of workouts (#4400)
Added support to
* filter workouts by multiple metrics
* rate and tag workouts
* view detailed information about the selected workout
* Preserving user-content in trainDB on rescan for workouts
Fixes #411
2024-05-20 13:57:58 -03:00
Alejandro Martinez
cfb8c2f6da Manage Perspectives - perspectives list cosmetics
- Disable in-place name edition
- Use double click to edit perspective
To match the behavior of similar lists.
2024-05-15 14:12:57 -03:00
Alejandro Martinez
f1bb83f302 Update Images default chart 2024-05-12 19:16:19 -03:00
Alejandro Martinez
5445ab6c04 Update snapshot builds
562ef17d7 Update Spanish translation (#4487)
57c11e076 Remove Ctrl+A shortcut for Add Cloud Account
cf2e8d809 Enable translation of Save Changes in SaveExitDialog
1b498903d Update German Translation
f97770fa9 GC CSV Export - rcad instead of cad for runs
7a11a6abd Initializing AllPlot::isPanning to false (#4482)
76dedfb48 Fix Average Speed aggregation
62993743d Images chart update on image drop and import
fdb6d1795 Python Web Chart - Don't accept drops
68ad04862 Update Images Python chart in default layout
2d8bdd742 FitRideFile - Decode GAP extra field in m/s
5073ba8b0 Add Images chart to default layout
c693ed6b1 FitRideFile - Extra fields 136, 143 and 144
4f5a0eb2e CP Chart - show/hide interval settings based on model and fitting selection (#4382)
0b144cc57 Train View: Coloring by powerzones in ErgFilePlot (#4479)
02835e3eb Added support for old Daum devices before 2001 (#4303)
71c72d665 Changed the standard colors for compare-mode (#4478)
118eafed8 FitRideFile : A devApp can replace another with same local id
1241c0a77 Use elapsed time for session (instead of timestamp) fix #4474
a1a76fbc3 WorkoutWizard - Don't save and close on Cancel
64c7ce3bd Improved search/filter box drop down menu icon (#4470)
[publish binaries]
2024-05-10 20:26:29 -03:00
Joachim Kohlhammer
8a9a43f0c6 Qt6: The signature of enterEvent changed (#4488)
Adapted to the new signature of enterEvent when using Qt6 (before this
change enterEvent was ignored with Qt6); added some additional override
specifiers
2024-05-09 09:37:31 -03:00
jgpallero
562ef17d7b Update Spanish translation (#4487) 2024-05-08 14:39:17 -03:00
Alejandro Martinez
57c11e076b Remove Ctrl+A shortcut for Add Cloud Account
It is not a frequent operation and it disables the use
of Ctrl+A for select all in Editor, which is more useful.
2024-05-07 12:22:29 -03:00
Alejandro Martinez
cf2e8d8096 Enable translation of Save Changes in SaveExitDialog
Also updated translation files to include the new strings
and remove the obsolete ones.
2024-05-07 10:30:05 -03:00
Alejandro Martinez
1b498903d8 Update German Translation
Contributed by Marcen at the users forum
2024-05-07 10:27:29 -03:00
Alejandro Martinez
f6237e02c4 Revert "DialWindow: Scaling font in both dimensions (#4469)"
This reverts commit 63a14d0edf.
2024-05-07 10:24:24 -03:00
Joachim Kohlhammer
63a14d0edf DialWindow: Scaling font in both dimensions (#4469)
Currently the font in DialWindow is only scaled to make the text fit
into the label vertically. This commit scales the font in both
dimensions and prevents cutting off the content.

The font is rescaled
* If the DialWindow itself is resized
* If the text set and is longer than the previous one
* Every 10 text-changes
2024-05-06 20:40:16 -03:00
Alejandro Martinez
f97770fa94 GC CSV Export - rcad instead of cad for runs
Fixes #4485
2024-05-06 19:07:58 -03:00
Joachim Kohlhammer
3e8ddd9f29 Qt6: Preventing crash in stacked LTMPlots (#4483)
In Qt6 the internal handling of QList (now actually a QVector) was
changed compared to Qt5. This results in reallocations / recreations of
the LTMSettings, destroying the objects whose pointers already have been
set to the LTMPlots.
This commit reserves the required space upfront, preventing the
reallocations thus keeping the pointers valid and preventing the crash
2024-05-04 12:59:06 -03:00
Joachim Kohlhammer
7a11a6abd4 Initializing AllPlot::isPanning to false (#4482)
AllPlot::isPanning was uninitialized, leading to unwanted (i.e. without
prior middleclick) panning.
This commit initializes AllPlot::isPanning explicitly to false.
2024-04-29 16:01:34 -03:00
Alejandro Martinez
76dedfb482 Fix Average Speed aggregation
It didn't set count so it defaulted to duration,
when it should use Moving Time for that purpose.
Also changed Recovery Points to 2*ln(RMSSD).
2024-04-28 15:48:53 -03:00
Alejandro Martinez
62993743d9 Images chart update on image drop and import
Image import notifies rideMetadataChanged for the item
Python chart re-evaluates the script on item changes
2024-04-26 20:38:26 -03:00
Alejandro Martinez
fdb6d17952 Python Web Chart - Don't accept drops
It is confusing for the user of Image gallery chart.
2024-04-26 17:48:54 -03:00
Alejandro Martinez
68ad048628 Update Images Python chart in default layout
Contributed by Marcen at the users forum
2024-04-26 17:48:16 -03:00
Alejandro Martinez
365ca0f1aa Deprecate remaining Todays Plan files
Complements 642eae9
2024-04-26 17:40:04 -03:00
Alejandro Martinez
2d8bdd7427 FitRideFile - Decode GAP extra field in m/s 2024-04-26 17:18:12 -03:00
Alejandro Martinez
924829f9f4 Add images and video for the wiki
[skip ci]
Contributed by Marcen at the users forum
2024-04-26 17:03:29 -03:00
Alejandro Martinez
5073ba8b0d Add Images chart to default layout
Complements b3df633
2024-04-25 21:17:11 -03:00
Alejandro Martinez
c693ed6b1c FitRideFile - Extra fields 136, 143 and 144
Decoded as Wrist HR, Body Battery and External HR.
Fixes #4480
2024-04-24 14:07:01 -03:00
Thies Lennart Alff
4f5a0eb2e1 CP Chart - show/hide interval settings based on model and fitting selection (#4382) 2024-04-23 11:11:08 -03:00
Joachim Kohlhammer
0b144cc57b Train View: Coloring by powerzones in ErgFilePlot (#4479)
Added support to color sections according to their power zone
* Optional coloring: Never (default), Always, Workout is stopped
* Optional tooltip giving information about current section (independent
  of coloring): Never (default), Workout is stopped
* Single sections covering multiple zones are split (for coloring /
  tooltip only)
* Tooltip shows starttime, duration, power (range if applicable), zone,
  W'bal-range
2024-04-22 11:48:07 -03:00
LateNightCoder0815
02835e3eb5 Added support for old Daum devices before 2001 (#4303)
Old Daum Electronic device "Ergobike Cardio" (comparable to the 4008 series and many other bikes) from before 2001 uses a slightly different RS232 protocol in some of the cases, which can be found here: http://www.ergo-lyps.de/de/download/v01/schnitt.zip . Additionally, it uses a boud rate of 4800.

As the old devices can not be detected by the checkversion (was not implemented at that time) I used a _profile of "OLD_DAUM" to identify the device in the configuration setting.
2024-04-21 08:45:54 -03:00
Joachim Kohlhammer
71c72d665f Changed the standard colors for compare-mode (#4478)
Changed the standard colors, used for compare-mode:
* Nice looking and distinguishable colors
* Separate color-sets for light- and darkmode

Additional fix + refactoring:
* Fixed a typo that prevented the background-color of ComparePanes to
  follow the color-scheme (was always white on my machine)
* Moved the definition of standardColor(int) from ComparePane.cpp to
  Colors.cpp, matching the declaration in Colors.h
2024-04-20 20:12:20 -03:00
grauser
118eafed89 FitRideFile : A devApp can replace another with same local id
fix #4477
2024-04-19 19:21:00 +02:00
grauser
1241c0a77b Use elapsed time for session (instead of timestamp)
fix #4474
2024-04-19 13:25:26 +02:00
Alejandro Martinez
a1a76fbc33 WorkoutWizard - Don't save and close on Cancel
When the user Cancel the file save dialog it is
better to do nothing since we have no filename
for save and it is likely what the user expects.
Fixes #4476
2024-04-18 21:38:46 -03:00
Paul Johnson
64c7ce3bd5 Improved search/filter box drop down menu icon (#4470)
Reuses the hamburger menu on the right side for easier
and more intuitive access to the filter menu.
2024-04-16 20:51:46 -03:00
Alejandro Martinez
d4405a65b5 Revert "Trigger Travis-ci macOS build with Qt5 update"
[skip AppVeyor]
This reverts commit 1e5d52a05a.
Regrettably brew update is too slow, lets wait travis images
get updated.
[skip linux]
[publish binaries]
2024-04-16 17:40:26 -03:00
Alejandro Martinez
f63c3e6e6d Trigger Travis-ci macOS build with Qt5 update
[skip AppVeyor]
[skip linux]
[publish binaries]
Last attempt failed due to lack of OSS credits.
2024-04-16 16:43:16 -03:00
Alejandro Martinez
1e5d52a05a Trigger Travis-ci macOS build with Qt5 update
[skip AppVeyor]
[skip linux]
[publish binaries]
2024-04-16 15:35:57 -03:00
Alejandro Martinez
8283c653e6 Trigger Travis-ci macOS build
[skip AppVeyor]
[skip linux]
[publish binaries]
2024-04-13 16:45:01 -03:00
Alejandro Martinez
71388fb56e Trigger AppVeyor-ci build
[skip travis]
[publish binaries]
2024-04-13 15:58:24 -03:00
Alejandro Martinez
2c9e9b9007 Trigger Travis-ci builds
[skip AppVeyor]
[publish binaries]
2024-04-13 13:36:37 -03:00
Alejandro Martinez
3d832ddd2c Version 3.7 - Development Build April 2024
First development build after v3.6 release.
[Publish Binaries]
2024-04-13 13:11:42 -03:00
Alejandro Martinez
3395c7a4c9 Fix 3b50dd8 for reentrancy
Changed static variable for a member one,
the problem was apparent when opening a
different athlete besides the initial one.
2024-04-12 12:10:50 -03:00
Alejandro Martinez
3b50dd81a9 RideCache - send less load update notifications
To minimize overhead and avoid crashes on Windows
Fixes #4471
2024-04-10 19:37:35 -03:00
Alejandro Martinez
a1a19d86a0 Update version information and defaults link 2024-04-09 16:39:47 -03:00
Alejandro Martinez
656cdc701d Change Zoomed Elevation Widget Position 2024-04-09 14:21:27 -03:00
Alejandro Martinez
edc3979504 Update FITmetadata.json to FIT SDK 21.133 2024-04-08 16:35:01 -03:00
Peter Kanatselis
424c635a08 Zoomed Elevation widget (#3793) 2024-04-08 14:31:31 -03:00
Joachim Kohlhammer
8718974722 Added a graphical splashscreen (#4468)
* Based on QSplashScreen
* Shrinking the image for low resolutions (screen width <= 1280, < 1024)
* Dynamically adding Golden Cheetahs version and build id
* Showing messages related to the current loading state (including the
  current counter)
* Closing the splashscreen as close as possible to showing the MainWindow
* The image (splashscreen.svg) was created using Inkscape
2024-04-08 11:34:55 -03:00
Joachim Kohlhammer
d0e536306f Added a configurable grayscale filter to RideMapWindow (#4417)
* Added a CSS-grayscale filter to OSM based maps in RideMapWindow
* Added a configuration-option for the intensity level (0..10)
* Configuration is persisted per Tile-Server
* Fixed the visibility of Google/OSM specific settings (previously the
  settings were only correct after selection of the other Maptype)
2024-04-07 08:36:33 -03:00
r.clista
8d0307ed10 Add ignore zeros LTM setting (#2927)
* Add 'ignore zeros' metric detail setting
* Draw gapped curve when ignoreZeros is set
* Hide Ignore Zeros when not available
* Consider special cases in compare mode too
Co-authored-by: Antonius Riha <antoniusriha@gmail.com>
Co-authored-by: Alejandro Martinez <amtriathlon@gmail.com>
2024-04-06 20:51:59 -03:00
Stefan Schake
69b0dd3c2b Zoom & Pan for the AllPlot (#2366)
* Add mouse wheel zoom capability to AllPlot, only when
  ctrl modifier is present to avoid conflict with scrolling,
  similar to Workout Editor.
* Add AllPlot panning by mouse wheel click-n-drag
2024-04-05 14:15:19 -03:00
Joachim Kohlhammer
0a7072e5be ErgFile: Coalescing neighbouring sections (#4462)
* ErgFile: Coalescing neighboring sections

In erg-mode, some ErgFiles have neighboring sections of same power.
This is fine for creators / editors of workouts but gives "wrong"
remaining section times from a athletes perspective, example:
* workout: 10 min @200 watts followed by 5 min @200 watts
* current situation: first counts down from 10:00 to 0, then from
  5:00 to 0
* for an athlete, the countdown should be from 15:00 to 0 instead

This change
* Added global config option to enable coalescing
* If enabled, coalesced sections are used globally
* Added a message to the WorkoutWindow (Properties) if the ErgFile
  contains coalesced sections
* Restricted coalescing to watt based workouts
2024-04-03 20:32:04 -03:00
Joachim Kohlhammer
2ce84cbefd Bound global action to QKeySequence::Quit (#4464)
This change allows to quit Golden Cheetah using a keyboard shortcut.
QKeySequence::Quit is Ctrl+q on Linux and Cmd+q on MacOS but unbound
on Windows, although Alt+F4 still works as usual there. 
See https://doc.qt.io/qt-6/qkeysequence.html#standard-shortcuts

Additionally set Qt::WaitCursor while shutting down Golden Cheetah to
indicate the application is blocked
2024-03-29 20:04:19 -03:00
Alejandro Martinez
fd1eed4ed2 Update German Translation
Contributed by Marcen at the users forum.
2024-03-27 19:03:50 -03:00
jgpallero
de4741ba89 Fix typos in Spanish translation (#4463) 2024-03-27 11:13:01 -03:00
luzpaz
67ac67c509 Fix various typos (#4383)
Found via `codespell -q 3 -S "*.pdf,*.slf,*.smf,*.ts,./deprecated,./contrib" -L ans,ded,nam,nd,parm,parms,serie `
2024-03-25 20:46:26 -03:00
enngq11k
16ccc43d7a Fixed rounding error on loading and saving erg files (#4455) 2024-03-25 15:45:18 -03:00
jeepingben
65deb0f7fa Multiple custom power curves 4460 (#4461)
In cases where this config was loaded and is being saved again, preserve the virtual power definition string.
2024-03-24 21:34:39 -03:00
r.clista
28c9af8754 Workout Editor: Support MRC flavoured qwkcode (#3112)
New action allows to select desired flavor and format is displayed
on top of qwkcode, default file extension is selected accordingly.
2024-03-24 19:49:09 -03:00
mattipee
159804284a Download Strava Routes as Workouts (#3413)
Allows to download Strava routes as GPX files automatically imported as workouts.
To access to private Routes it is necessary to grant read_all permission at authorization
time, existing Strava users need re-authorization.
Downloaded files are named as Strava-Route-id-RouteName.gpx
2024-03-23 18:12:54 -03:00
Joachim Kohlhammer
ce7bbe11ed Replaced the icons in the TrainBottomBar (#4453)
* Replaced the icons in the TrainBottomBar

* Replaced the icons from oxygen (png) by new ones from breeze (svg)
* Added support for dark- and light-mode
* Grouped the icons by function
* Added a hover-effect to the icons
* The new theme fits better into the overall appearance
* Made the separators visible also for dark themes
2024-03-22 18:26:33 -03:00
Alejandro Martinez
ba47ff741a Remove special case for Sidebar background color
Intended for macOS Yosemite it has a bug which doesn't
allow the Sidebar background color be changed on macOS
Sonoma and may be other versions, since the forced color
is now default for macOS and Yosemite has been phased out
long time ago, let's remove this.
Fixes #4459
2024-03-22 18:20:33 -03:00
Alejandro Martinez
bcf8ea7e6a Update macOS build instructions for current master
[skip ci]
Using latest versions.
2024-03-19 19:34:37 -03:00
Alejandro Martinez
e3ad77e9c6 Remove levmar dependency
It is not being used
2024-03-19 16:36:34 -03:00
Alejandro Martinez
2c3df3122d Update snapshot builds
Summary of functional changes from v3.6 release:
ea641a6 FitRideFile - Added support for new message structure (#4456)
642eae9 Deprecate Today's Plan integration
ecdfe0c Deprecate export to KML files
2b5f1d7 Enable Pace metric for Walking
663fd78 Rename fatigue zones for consistency
2afd38c Initialized mode when parsing a zwo-file (#4448)
a0b6b17 Fixed some valgrind findings (#4445)
f174d74 Fix memory leak in SplitActivityWizard
d335ff4 Charts/PfPvPlot (QA): allow vertical scales up to 2500N (#4444)
b3df633 Drag and Drop Images onto a ride
50c305b bluetooth FTMS fix to get device speed  (#4440)
bd75198 Add Context help for Create/Edit User Metrics
809d72d MainWindow gets drag/drop from Overview
46545d6 Don't use Ctrl+C to check for new activities
07d1197 Update German Translation
49cf634 Upgraded Qwt to 6.2 (branch: qwt-multiaxes) (#4427)
ea044a0 Accelerators are QKeySequence not tr strings
31636b1 Update Travis-ci macOS builds to xcode 14.2
c46a99e Update Spanish translation (#4426)
b6aefcc Fix some non-translatable strings and update ts files
6c2a260 DataFilter - isAero
bd4bed1 Upgrade Travis-ci builds to macOS 12.6
6b1dbf4 Added Bluetooth pairing to the device wizard (#4422)
c0c8f57 Update FIT SDK definitions to 21.126 (#4423)
0dd4bf6 Cursor in text workout editor was invisible
6e5b950 Fix crash on metadata config
1dd7faa Interval Metadata
d9abb58 Datafilter xdataseries(), xdataunits() and xdatavalues()
5fb3bbf FIT parser bounds check when adding new series
943deb6 Generic Support for Session and Lap in FIT files
146f9ea Fix Weekly tiles in default Trends layouts
ec0653f ErgFilePlot - realtime curves honor FFWD/RWND and lap F/B
43368ad Mapview: Added interactivity to the Smallplot (#4408)
72de6bb Fix lap data auto-reset in slope workouts
c2f440c Fix broken workout directory check for the first start (#4410)
b095b40 Fix shortcuts not available due to translations
e6ff1a1 Python Chart Editor Cosmetics
00e182c Better user experience when drawing segments on the map (#4403)
f746f73 GPX parser - support ns3 TrackPointExtension name
9ae7521 Upgrade Travis-ci macOS version to macOS 11.6
e8132b1 Upgrade Travis-ci Linux version to Ubuntu 20.04
8f2ba0e Special case Start Date and Time in the cache
110652b Update German translation
fabc344 Add Wahoo PowrLink
f783814 Train library - add path to the list of possible errors
48d91d0 Fix issues after perspective switch (#786)
59a8ca2 Implemented compare mode for RideMapWindow (#786)
733db9c Ignore dot folders on athlete open/backup/delete
951e5f3 Fix crash on invalid perspective filter
[publish binaries]
2024-03-12 18:27:19 -03:00
Alejandro Martinez
ea641a6955 FitRideFile - Added support for new message structure (#4456)
Main change is activity, session and lap messages come
before than record messages so this would be the minimum
change to adapt to the new structure while still supporting
the old one.
Fixes #4451
2024-03-11 16:01:16 -03:00
Joachim Kohlhammer
a1f02e925f Qt6: Fixed flickering MainWindow (#4452)
* Qt6: Fixed flickering MainWindow

When opening a Mapchart for the first time after start of GC, the
MainWindow used to shrink and be maximized again afterwards
automatically, matching the description in
https://forum.qt.io/topic/141398/qwebengineview-closes-reopens-window-when-added-dynamically

By adding and removing a QWebEngineView before showing MainWindow,
this flicker can be avoided

* Added empty HTML to RideMapWindow

This fix avoids flicker for the RideMapWindow in (un-)maximized windows
(only if the chart was already part of the layout on startup)
2024-03-10 09:28:24 -03:00
Alejandro Martinez
642eae96cb Deprecate Today's Plan integration
Fixes #4450
2024-03-02 19:02:30 -03:00
Alejandro Martinez
dbf8877c53 Disable OpenGL for QtChart series
When Qt version is 6.4 or higher since it doesn't work
and it creates "ghost" windows. We can revert this if it
gets fixed, but it happens even using Qt 6.6.2
2024-03-01 18:05:59 -03:00
Alejandro Martinez
ecdfe0c4e2 Deprecate export to KML files
Related to #3983, see discussion there for the rationale.
2024-03-01 15:22:29 -03:00
Alejandro Martinez
2b5f1d749b Enable Pace metric for Walking 2024-02-28 17:12:36 -03:00
Alejandro Martinez
663fd7833a Rename fatigue zones for consistency
Fixes #4434
2024-02-28 16:19:50 -03:00
Joachim Kohlhammer
2afd38cb30 Initialized mode when parsing a zwo-file (#4448)
When zwo workout files are read, mode was not set but the original value
kept. This could lead to wrong perspective switches in Train-mode.
2024-02-20 14:09:57 -03:00
Joachim Kohlhammer
a0b6b17072 Fixed some valgrind findings (#4445)
Fixed some findings of valgrind (a tool to detect memory management bugs):
* Mismatched free() / delete / delete [] (HrPwPlot.cpp)
* Conditional jump or move depends on uninitialised value(s) (other files)
2024-02-09 20:58:35 -03:00
Alejandro Martinez
f174d74dcd Fix memory leak in SplitActivityWizard 2024-02-09 10:06:06 -03:00
Alejandro Martinez
35433b4f65 Add assignment operators to some classes (#3937)
The implicitly defined assignment operator for classes having custom
defined copy constructor is deprecated.
This patch adds explicit assignment operators.
XDataSeries assignment operator now deletes XDataPoints pointed by
datapoints array in the target and creates new ones for the source,
this required a change in the way XDataSeries is used in JSON parser,
which was based on default assignment operator semantics.
2024-02-09 10:02:39 -03:00
Alejandro Martinez
81fc763a4f Revert "Merge branch 'add_assignment_operator' of https://github.com/andreasbuhr/GoldenCheetah into andreasbuhr-add_assignment_operator"
This reverts commit 4e09cd0717, reversing
changes made to 0c4107d78b.
2024-02-05 17:53:06 -03:00
Alejandro Martinez
f2291f4522 Merge branch 'andreasbuhr-add_assignment_operator' 2024-02-04 19:19:03 -03:00
Alejandro Martinez
4e09cd0717 Merge branch 'add_assignment_operator' of https://github.com/andreasbuhr/GoldenCheetah into andreasbuhr-add_assignment_operator 2024-02-04 19:18:42 -03:00
Alejandro Martinez
0c4107d78b Qt6 - Replace deprecated 2 parameters qChecksum 2024-02-04 17:44:27 -03:00
Gabriel M. Beddingfield
d335ff425c Charts/PfPvPlot (QA): allow vertical scales up to 2500N (#4444)
The vertical axis on the QA plots (pedal force, Newtons) was stuck at
600N, even if the ride data exceeded it. The code that calculated the
max force for the activity was apperently trying to throw out outliers
(defined as "more than 2500N" -- 562 lbf)... but when finding the "max
force" the value was seems to have accidentally been typed in as
"255". This created logically dead code:

    maxAEPF = 600;
    ...
    if (aepf < 255 && aepf > maxAEPF) maxAEPF = aepf;

Thus, the max is never updated.

This patch changes the filter value from 255 to 2500 (as is indicated
to be the intent elsewhere in the source file).
2024-02-04 17:04:52 -03:00
Alejandro Martinez
76922846f8 Update snapshot builds
Functional changes from last snapshot:
b3df63378 Drag and Drop Images onto a ride
50c305b7f bluetooth FTMS fix to get device speed  (#4440)
bd751988e Add Context help for Create/Edit User Metrics
809d72d00 MainWindow gets drag/drop from Overview
46545d6e7 Don't use Ctrl+C to check for new activities
07d1197c6 Update German Translation

There are also lot of changes related to QT6 refactor but,
in principle, they should not affect snapshot builds using Qt5.15

Previous changes from v3.6 release
ee39d19adf
[publish binaries]
2024-02-03 11:27:36 -03:00
Joachim Kohlhammer
425db688da Qt6: Fixed a crash related to drag & drop (#4443)
* Qt6: Fixed a crash related to drag & drop

Qt6 changed the signature of the method mimeData in QTreeWidget and
QTableWidget from
Q...::mimeData(const QList<...>) const
to
Q...::mimeData(const QList<...>&) const
therefore ignoring local implementations and falling back to the
base-implementation with the default-serialization.
This PR supports both Qt5 and Qt6 by a selecting the matching signature
based on the Qt-version. Additionally the specifier override was
added to Q...::mimeData, Q...::mimeTypes and some drag&drop-related
event-handlers to prevent this kind of error for future versions.

* Fixed drag&drop for seasons

In Qt6, QList::count() returns q qsizetype instead of QT5s int,
therefore casting the number of seasons to int when serializing for
drag & drop
2024-02-02 20:17:32 -03:00
Alejandro Martinez
94d4bf7b9d QTextStream::readAll is too slow in Qt6 for rideDB
Using the QString from QByteArray constructor and
QFile::readAll is way faster on Qt6.x and similar on Qt5.15
2024-01-30 23:00:45 -03:00
Mark Liversedge
b3df633787 Drag and Drop Images onto a ride
.. drag and dropping images into a ride will store them
   in the media folder and add the filename to the "Images"
   metadata tag which contains a list separated by newlines.

   The metadata does not include the full path since we may
   change the path in future releases
2024-01-30 15:50:33 +00:00
Odald
50c305b7f2 bluetooth FTMS fix: if condition was always false, so no speed was reported... (#4440)
!FTMS_MORE_DATA == 0
flags & 0  == 0
-> if statement is always false
2024-01-29 10:17:16 -03:00
Alejandro Martinez
bd751988e3 Add Context help for Create/Edit User Metrics
Also updated to Favourites instead of Intervals/etc.
2024-01-27 17:19:32 -03:00
Mark Liversedge
809d72d000 MainWindow gets drag/drop from Overview
.. the chartspace widget used by the athlete view and
   overview chart now passes drag and drop events up to
   mainwindow so they can be processed
2024-01-27 10:27:39 +00:00
Alejandro Martinez
9119fe05e0 Fix crash when program is empty using Qt6
Failed QString[i] assert "i>=0 && i<size()"
Reported by Marcen at the users forum.
2024-01-25 17:31:42 -03:00
Alejandro Martinez
66ee605998 Recognize Joachim Kohlhammer
For his contributions with new features, bug fixes
and QT6 migration.
https://github.com/GoldenCheetah/GoldenCheetah/commits?author=thejockl
2024-01-25 09:13:53 -03:00
Alejandro Martinez
4224fd193c Qt6 count method has changed return type
From int to qsizetype, and that brakes LTM charts serialization.
Since curves count is a small number and to preserve backward
compatibility, convert count result to int.
2024-01-23 20:08:50 -03:00
Alejandro Martinez
b95d901ad3 RideItem - remove unused operator >
Fixes #4438
2024-01-23 20:00:30 -03:00
Alejandro Martinez
ca6c6ffcd1 Fix crash on DataFilter aggregate when by is empty
Continuation of previous commit, the empty result
can also be non numeric.
2024-01-22 19:22:39 -03:00
Alejandro Martinez
46c6ee1d91 Fix crash on DataFilter aggregate when by is empty
Since the empty Result has type number, adding an empty string
to the list is ignored by asString, adding number which is 0
in this case, fixes the issue.
Reported Marcen at the users forum.
2024-01-22 10:14:05 -03:00
Alejandro Martinez
573967fe47 GenericSelectTool - Avoid crash
Don't dereference the end() iterator
2024-01-18 15:03:26 -03:00
grauser
a4cc418b6e Add include 2024-01-18 17:37:44 +01:00
Alejandro Martinez
42aa24108c Revert "There are two overloads for QStringList and QVector<QString> (#3977)"
This reverts commit 466bdf1939.
PythonChart connect failed without the removed overload,
as reported in #3893
2024-01-18 11:47:01 -03:00
grauser
0be34094aa No more QSysInfo:MacVersion 2024-01-18 15:25:57 +01:00
Alejandro Martinez
acd76507e2 Replace QButtonGroup::buttonClicked(int) by idClicked(int)
Deprecated in Qt6
2024-01-18 10:54:55 -03:00
Damien Grauser
154d93a8df QTBUG-32789 was resolved 2024-01-18 13:32:19 +01:00
Damien Grauser
b47b72b013 QT6 : no more macextras 2024-01-18 13:31:43 +01:00
Alejandro Martinez
b12984b94c Fix typo from previous commit 2024-01-17 17:39:04 -03:00
Alejandro Martinez
dc4e26fbf5 From Qt 6.6 qint128 is a typedef
https://doc.qt.io/qt-6/qttypes.html#qint128-typedef
2024-01-17 15:20:28 -03:00
Alejandro Martinez
eb2ba14c68 QDomDocument::ParseResult introduced in Qt 6.5
QDomDocument::setContent now requires explicit bool conversion.
https://doc.qt.io/qt-6/qdomdocument.html#setContent
2024-01-17 09:59:06 -03:00
Alejandro Martinez
c553de5216 Replace QRegExpValidator by QRegularExpressionValidator
And QRegExp by QRegularExpression, they were deprecated.
2024-01-16 14:56:01 -03:00
Alejandro Martinez
e95608e4bc QByteArray::append(const QString &str) a is deprecated
The Unicode data was converted into 8-bit characters using
QString::toUtf8(), now it must be explicit.
2024-01-16 14:38:19 -03:00
Alejandro Martinez
21faf53d3c Change QDate to QDateTime conversions, specifying time
The QDateTime constructor taking a QDate as argument is deprecated.
QDate::startOfDay() should be used instead when converting a QDate
to a QDateTime. This makes clear what time is used in this conversion.
2024-01-16 14:22:06 -03:00
Alejandro Martinez
894eb421e3 QTableWidgetItem::setBackgroundColor is deprecated - adapt code 2024-01-16 14:11:00 -03:00
Alejandro Martinez
4b4006002e Replace QWheelEvent::delta by angleDelta 2024-01-16 10:35:24 -03:00
Alejandro Martinez
95b4a4969c R - Replace QRegExp by QRegularExpression 2024-01-16 10:34:41 -03:00
Alejandro Martinez
8e2eb3fc18 Remove duplicate include from previous commit 2024-01-16 10:01:35 -03:00
Alejandro Martinez
1f999a3957 Python - Replace QRegExp by QRegularExpression 2024-01-15 15:04:09 -03:00
Alejandro Martinez
c054d7c11a Adapt to signal names in QWebEngineDownloadRequest
They changed from QWebEngineDownloadItem, deprecated in Qt6
2024-01-15 10:46:16 -03:00
Alejandro Martinez
4e03b7d15f Bluetooh error signal renamed errorOccurred in Qt6 2024-01-15 09:44:05 -03:00
Alejandro Martinez
f138839d0f Angle is not available on Qt6
https://doc.qt.io/qt-6/opengl-changes-qt6.html#removal-of-angle
2024-01-14 17:35:35 -03:00
Joachim Kohlhammer
138c68a4e6 Qt6: Fixed connections (#4436)
In UserChart and DownloadRideDialog the deprecated signal QComboBox::currentIndexChanged(QString)
was connected to a slot without parameters. In Qt6 this created a warning.
Changed to signal QComboBox::currentIndexChanged(int)
2024-01-14 12:44:29 -03:00
Joachim Kohlhammer
b9e6542a90 Prevent the use of a deleted QVariant constructor (#4435)
In Qt6.4++, the templated constructor QVariant(T) is marked as =delete,
making compilation fail. By casting the return value to (const char*),
the right QVariant constructor is explicitly selected
2024-01-14 10:08:29 -03:00
Joachim Kohlhammer
bf28d7398c Fixed a crash in RideMapWindow (#4437)
Fixed a crash when dereferencing const_end()-iterator while searching
latest selected interval
2024-01-14 08:29:13 -03:00
Alejandro Martinez
1fb92d1bf5 Recognize Andreas Buhr
Great work adapting GoldenCheetah code to Qt6
https://github.com/GoldenCheetah/GoldenCheetah/commits?author=andreasbuhr
2024-01-13 16:51:25 -03:00
Alejandro Martinez
6407ada035 Add Moc include for Perspective property
In the line of #3980
2024-01-13 16:44:39 -03:00
Alejandro Martinez
646b2151f5 WebPageWindows - Fix typo
Introduced by c72b7d7a4f
2024-01-13 16:31:56 -03:00
Alejandro Martinez
35bd666bf2 Computriner - remove deprecated QString::midRef 2024-01-13 16:22:21 -03:00
Alejandro Martinez
153e83fa1d Fix std::min type ambiguity 2024-01-13 16:17:24 -03:00
Alejandro Martinez
c14891aba0 MergeActivityWizard - Fix conversion error
The variable was unused anyway
2024-01-13 16:05:00 -03:00
Alejandro Martinez
81ddcd5ff8 QMetaProperty::isUser has no parameter in Qt6
And it is optional in Qt5.15
2024-01-13 15:58:44 -03:00
Alejandro Martinez
a65390167d MainWindow - Fix QColor to String invalid conversion 2024-01-13 15:55:57 -03:00
Alejandro Martinez
379743e50b Settings - fix Qt6 compatibility 2024-01-13 15:45:53 -03:00
Alejandro Martinez
d37d67520a AthletePages - explicit conversion to QUuid 2024-01-13 15:37:35 -03:00
Alejandro Martinez
628b74c974 QStandardPaths::DataLocation deprecated in Qt6
In Qt5 returns the same value as AppLocalDataLocation.
2024-01-13 15:34:11 -03:00
Alejandro Martinez
c47743fe12 Azum - SkipEmptyParts is in Qt now 2024-01-13 15:24:34 -03:00
Alejandro Martinez
8aa08973ed Azum - Fix QString compatibility for Qt6 2024-01-13 15:18:47 -03:00
Alejandro Martinez
a68c1b2356 QTextStream::setEncoding not setCodec in Qt6 2024-01-13 15:07:33 -03:00
Alejandro Martinez
c4a8f820a6 QMetaProperty::isUser has no parameter in Qt6
And it is optional in Qt5.15
2024-01-13 14:36:21 -03:00
Alejandro Martinez
831027286f Qt6: utf8 for QTextStream is the default
Complements #3953
2024-01-13 14:32:50 -03:00
Alejandro Martinez
7c8d4a3066 Replace QPalette::Background by QPalette::Window
Like #3951
2024-01-13 14:31:32 -03:00
Alejandro Martinez
8045855deb Replace deprecated QDateTime::fromTime_t
by QDateTime::fromSecsSinceEpoch
2024-01-13 13:42:12 -03:00
Alejandro Martinez
c72b7d7a4f Replace QWebEngineDownloadItem for Qt6
It was renamed as QWebEngineDownloadRequest
2024-01-13 11:36:33 -03:00
Alejandro Martinez
1807d0426e Replace QSound by QSoundEffect
QSound was deprecated for Qt6
2024-01-13 11:35:33 -03:00
Joachim Kohlhammer
556b588b3f Using one more Bluetooth enum from its namespace (#4433)
similar to #3842
2024-01-13 07:49:44 -03:00
Joachim Kohlhammer
a0d25a89a9 Removed one of two overloads for QVector<QString> and QStringList (#4432)
They are the same in Qt6
2024-01-13 03:56:52 -03:00
Andreas Buhr
0c5e4435b3 Qt6: adapt build system to accept Qt6 (#3949)
Adapts the build system to accept Qt6 and enable testing.
It accounts for webengine rename to webenginequick.
It further drags in qtcore5compat, which provides QRegExp,
QXmlInputSource, and QXmlSimpleReader. Those classes are not
part of Qt6, but they are provided in qtcore5compat to reduce
the porting effort in projects like GoldenCheetah.
Minimum supported version is Qt 5.15 now
2024-01-12 22:10:58 -03:00
Alejandro Martinez
667d483bc4 Merge branch 'andreasbuhr-replace_qdesktopwidget_usage' 2024-01-12 19:22:40 -03:00
Alejandro Martinez
9761873d7a Merge branch 'replace_qdesktopwidget_usage' of https://github.com/andreasbuhr/GoldenCheetah into andreasbuhr-replace_qdesktopwidget_usage 2024-01-12 19:21:44 -03:00
Alejandro Martinez
88746dd046 Remove usage of QGLWidget for Qt6
QGLWidget was deprecated and is removed in Qt 6
Fixes #3976
2024-01-12 16:52:20 -03:00
Joachim Kohlhammer
9c8ea778ba Removed an unused timer (#4431)
Removed a timer object of type QTime that only utilizes methods removed
in Qt6 but is never read
2024-01-12 15:26:14 -03:00
Alejandro Martinez
cf71437d79 Qt6: utf8 for QTextStream is the default
Fixes #3953
2024-01-12 11:28:30 -03:00
Andreas Buhr
fbabe2aa36 Qt6: Add QRegExp include and adapt usage (#3960) 2024-01-12 10:39:20 -03:00
Andreas Buhr
e77b3ff4d0 Replace deprecated QSignalMapper::mapped signalD
Fixes #3986

The QSignalMapper::mapped signal does not exist any more and
was replaced by mappedString, mappedInt, and mappedObject.
This patch adapts its usages and only transitions to
new style signal-slot connection syntax.
2024-01-12 09:54:13 -03:00
Andreas Buhr
58cb8954eb Qt6: QSettings defaults to UTF-8, no setIniCodec necessary (#3972) 2024-01-11 20:44:25 -03:00
Andreas Buhr
466bdf1939 There are two overloads for QStringList and QVector<QString> (#3977)
These are not required in Qt6, as QStringList is an QVector<QString>
2024-01-11 20:22:20 -03:00
Alejandro Martinez
408709c1d6 Merge branch 'andreasbuhr-more_fixes_around_margins' 2024-01-11 18:16:55 -03:00
Alejandro Martinez
e95e347653 Merge branch 'more_fixes_around_margins' of https://github.com/andreasbuhr/GoldenCheetah into andreasbuhr-more_fixes_around_margins 2024-01-11 18:13:30 -03:00
Andreas Buhr
0d8167999e Qt6: remove QStringList declaration (#3963) 2024-01-11 16:14:41 -03:00
Andreas Buhr
f396630f34 Some fixes around QString (#3970) 2024-01-11 14:11:15 -03:00
Andreas Buhr
2333d185d1 Add some necessary includes (#3981) 2024-01-11 12:41:47 -03:00
Andreas Buhr
a0582445a0 Some more workarounds about iterators which cannot +1 (#3979) 2024-01-11 11:41:08 -03:00
Andreas Buhr
b329b26507 QMap::const_iterator cannot do +1 any more. Workaround this. (#3974) 2024-01-11 10:51:35 -03:00
Andreas Buhr
d71bb540c1 Qt6: Remove usage of QHashIterator (#3969)
QHashIterator is no longer able to iterate over QMultiHash, even
though it is documented to be.
This patch removes usages of QHashIterator on QMultiHash.
2024-01-11 08:50:23 -03:00
Andreas Buhr
e2ccf121f2 workaround circular dependency for qt6 (#3980) 2024-01-11 08:19:22 -03:00
Andreas Buhr
a5f5185ceb QWebEnginePage::view was removed (#3968) 2024-01-11 04:23:08 -03:00
Andreas Buhr
107e2dbc49 Qt6: Remove call to qRegisterMetaTypeStreamOperators (#3967)
Stream operator registration is now automatic, see
https://doc.qt.io/qt-6/qtcore-changes-qt6.html
2024-01-10 20:57:20 -03:00
Andreas Buhr
31c6270b4c Qt6: replace toTime_t by toSecsSinceEpoch (#3964) 2024-01-10 20:30:09 -03:00
Andreas Buhr
5b3aadce46 Qt6: adapt checksum method (#3962) 2024-01-10 20:12:10 -03:00
Andreas Buhr
f467053763 Qt6: add QStringRef include (#3965) 2024-01-10 19:29:44 -03:00
Andreas Buhr
15d2574f1d Use factory method for QLowEnergyController (#3975)
Directly calling QLowEnergyController's constructor was deprecated
2024-01-10 17:23:19 -03:00
Andreas Buhr
360b740dad adapt SSL protocol name (#3954)
QSsl::TlsV1SslV3 has been renamed to TlsV1_0.
See
https://doc.qt.io/qt-5/qssl.html#SslProtocol-enum

This might be merged at any time.
2024-01-10 16:51:52 -03:00
Andreas Buhr
ef43590fa0 Replace QPalette::Background by QPalette::Window (#3951)
Both QPalette::Background and QPalette::Window have the value 10,
there is no difference.
See https://doc.qt.io/qt-5/qpalette.html#ColorRole-enum
2024-01-10 15:52:51 -03:00
Andreas Buhr
63c9c124ac MidButton has been renamed to MiddleButton (#3952) 2024-01-10 13:47:08 -03:00
Andreas Buhr
ec86b505fc QProcess::start(path) is deprecated - adapt code (#3948) 2024-01-10 12:48:03 -03:00
Andreas Buhr
fcbb9f8481 QWebEngineDownloadItem::path is deprecated - adapt code (#3943) 2024-01-10 12:47:32 -03:00
Andreas Buhr
05fd315359 QFileInfo::created is deprecated - adapt code (#3946) 2024-01-10 11:06:01 -03:00
Andreas Buhr
9c9d066143 QTableWidgetItem::setBackgroundColor is deprecated - adapt code (#3945) 2024-01-10 11:03:28 -03:00
Andreas Buhr
726d299ca0 QString::sprintf is deprecated - adapt code (#3944) 2024-01-10 09:58:12 -03:00
Alejandro Martinez
46545d6e72 Don't use Ctrl+C to check for new activities
Fixes #4430 introduced by ea044a0c while fixing a typo.
2024-01-10 09:30:10 -03:00
Alejandro Martinez
07d1197c67 Update German Translation
Contributed by Marcen at the users forum
2024-01-10 09:25:58 -03:00
Andreas Buhr
50f1266a76 QSet::toList is deprecated - adapt code (#3947) 2024-01-10 08:17:00 -03:00
Andreas Buhr
077947c9fe Fix QDir initialization (#3971) 2024-01-09 20:58:33 -03:00
Andreas Buhr
32d10609d7 Replace QColor::dark by QColor::darker and light by lighter (#3941)
QColor::dark and QColor::light are deprecated. This patch adapts
the code to use QColor::darker and QColor::lighter.
2024-01-09 20:48:17 -03:00
Andreas Buhr
15d648b402 Use QPainter::setTransform instead of QPainter::setMatrix (#3940)
QPainter::setMatrix is deprecated. This patch replaces
usage of setMatrix by usage of setTransform. and
removev QMatrix mentions
2024-01-09 20:45:37 -03:00
Andreas Buhr
d733099a6f Replace qStableSort by std::stable_sort (#3936)
qStableSort is deprecated. This patch replaces all usages by
std::stable_sort.
2024-01-09 16:44:03 -03:00
Andreas Buhr
84c29e8610 Specify text encoding in several places (#3935)
Conversion from QString to QByteArray is deprecated in Qt 6.
It will be required to specify the encoding. This patch
adapts several places to specify the encoding as UTF8.
This should be no behavior change, as encoding in UTF8 was the
default in the now deprecated methods, see
https://doc.qt.io/qt-5/qbytearray-obsolete.html#operator-2b-eq-3
2024-01-09 16:40:45 -03:00
Andreas Buhr
413c3b6086 Specify encoding when communicating with DropBox (#3933)
QByteArray::append(QString) was deprecated. It is now required
to specify an encoding. This patch adds the corresponding calls
to the communication with DropBox.
This should not be a behavior change, as UTF8 was the default
when converting from QString to QByteArray.
2024-01-09 16:40:08 -03:00
Andreas Buhr
ad0197b272 Specify encoding when communicating with TodaysPlan (#3932)
Conversion from QString to QByteArray is deprecated in Qt 6.
It will be required to specify the encoding. This patch
adapts the interaction with TodaysPlans API to specify the
encoding as UTF8.
This should be no behavior change, as encoding in UTF8 was the
default in the now deprecated methods, see
https://doc.qt.io/qt-5/qbytearray-obsolete.html#operator-2b-eq-3
.
2024-01-09 16:39:30 -03:00
Andreas Buhr
0e82904157 Specify encoding when communicating with OAuth (#3934)
Conversion from QString to QByteArray is deprecated in Qt 6.
It will be required to specify the encoding. This patch
adapts the interaction with an OAuth API to specify the
encoding as UTF8.
This should be no behavior change, as encoding in UTF8 was the
default in the now deprecated methods, see
https://doc.qt.io/qt-5/qbytearray-obsolete.html#operator-2b-eq-3
2024-01-09 16:23:14 -03:00
Andreas Buhr
efae13dcb1 Change QDate to QDateTime conversions, specifying time (#3927)
The QDateTime constructor taking a QDate as argument is deprecated.
QDate::startOfDay() should be used instead when converting a QDate
to a QDateTime. This makes clear what time is used in this conversion.
This patch adapts the code to this.
2024-01-09 14:01:55 -03:00
Andreas Buhr
90cddb9d35 Replace qVariantFromValue by QVariant::fromValue (#3926)
The function qVariantFromValue is deprecated and was replaced
by QVariant::fromValue. This patch adapts the code accordingly.
2024-01-09 13:38:20 -03:00
Andreas Buhr
762002cc0d Initialize QFlags by default constructor (#3925)
Initializing QFlags by "0" is deprecated. This patch changes all
code places which does this to use the default constructor.
2024-01-09 13:30:29 -03:00
Andreas Buhr
954fe97769 Replace QDate::shortDayName by QLocale::dayName (#3922)
QDate::shortDayName was deprecated. This patch replaces all usages
by QLocale::dayName.
2024-01-09 12:49:25 -03:00
Andreas Buhr
edf28464d3 Replace QTime by QElapsedTimer to measure timings (#3924)
Usage of QTime to measure timings is deprecated. This patch
replaces all usages by QElapsedTimer.
2024-01-09 11:32:18 -03:00
Andreas Buhr
ccdb48fdeb Replace QList::swap by QList::swapItemsAt (#3923)
QList::swap was renamed to QList::swapItemsAt. This patch adapts
the source code accordingly.
2024-01-09 10:01:14 -03:00
Andreas Buhr
d5df3ad454 Use hex and endl from Qt namespace (#3919)
Using hex and endl from QTextStream's namespace is deprecated.
Using those from Qt:: namespace instead.
2024-01-09 08:44:01 -03:00
Andreas Buhr
28d8390fac Replace QFontMetrics::width by QFontMetrics::horizontalAdvance (#3921)
QFontMetrics::width was deprecated. This patch replaces all usages
by QFontMetrics::horizontalAdvance.
It also replace three usages of QTextEdit::setTabStopWidth
by QTestEdit::setTabStopDistance.
2024-01-09 08:26:43 -03:00
Andreas Buhr
f15cb9cf35 replace qrand() by QRandomGenerator::global()->generate() (#3918)
qrand() was deprecated. Instead, generate() is called on
the global QRandomGenerator singleton.
QRandomGenerator::global is guaranteed to be well initialized.
There is no need to seed using qsrand().
2024-01-09 06:03:55 -03:00
Andreas Buhr
e102d36b43 Replace QLists toSet() method by QSet constructor (#3920)
The toSet() method was deprecated. This patch changes its usages
to use the QSet constructor.
2024-01-08 21:08:10 -03:00
Andreas Buhr
d39a9f0c05 Replace QString::(Skip|Keep)EmptyParts by Qt::(Skip|Keep)EmptyParts (#3917)
QString::SkipEmptyParts and QString::KeepEmptyParts are deprecated,
they have been moved to the Qt:: namespace. This patch adapts
the code accordingly.
2024-01-08 21:05:00 -03:00
Andreas Buhr
e84354ff63 Replace QString::null by QString() (#3916)
QString::null was deprecated. Using the default constructor
is the way to go now.
2024-01-08 20:48:09 -03:00
Andreas Buhr
4340c74d93 Use QtBluetooth enums from their namespace (#3842)
For increased type safety, some enums have been changed to
scoped enums in Qt 6.2, see
https://codereview.qt-project.org/c/qt/qtconnectivity/+/337069
https://codereview.qt-project.org/c/qt/qtconnectivity/+/336678
This patch adapts GoldenCheetah to this change.
Since C++11, enums inject their symbols in both their own
and their parent namespace, so this patch can be merged right
now.
2024-01-08 19:44:22 -03:00
Alejandro Martinez
84a024db21 Trigger Travis-ci macOS build
[skip AppVeyor]
[skip linux]
Continuation of ee39d19
[publish binaries]
2024-01-07 13:46:00 -03:00
Alejandro Martinez
ee39d19adf Update snapshot builds
Summary of changes from v3.6 release:
49cf634 Upgraded Qwt to 6.2 (branch: qwt-multiaxes) (#4427)
ea044a0 Accelerators are QKeySequence not tr strings
31636b1 Update Travis-ci macOS builds to xcode 14.2
c46a99e Update Spanish translation (#4426)
b6aefcc Fix some non-translatable strings and update ts files
6c2a260 DataFilter - isAero
bd4bed1 Upgrade Travis-ci builds to macOS 12.6
6b1dbf4 Added Bluetooth pairing to the device wizard (#4422)
c0c8f57 Update FIT SDK definitions to 21.126 (#4423)
0dd4bf6 Cursor in text workout editor was invisible
6e5b950 Fix crash on metadata config
1dd7faa Interval Metadata
d9abb58 Datafilter xdataseries(), xdataunits() and xdatavalues()
5fb3bbf FIT parser bounds check when adding new series
943deb6 Generic Support for Session and Lap in FIT files
146f9ea Fix Weekly tiles in default Trends layouts
ec0653f ErgFilePlot - realtime curves honor FFWD/RWND and lap F/B
43368ad Mapview: Added interactivity to the Smallplot (#4408)
72de6bb Fix lap data auto-reset in slope workouts
c2f440c Fix broken workout directory check for the first start (#4410)
b095b40 Fix shortcuts not available due to translations
e6ff1a1 Python Chart Editor Cosmetics
00e182c Better user experience when drawing segments on the map (#4403)
f746f73 GPX parser - support ns3 TrackPointExtension name
9ae7521 Upgrade Travis-ci macOS version to macOS 11.6
e8132b1 Upgrade Travis-ci Linux version to Ubuntu 20.04
8f2ba0e Special case Start Date and Time in the cache
110652b Update German translation
fabc344 Add Wahoo PowrLink
f783814 Train library - add path to the list of possible errors
48d91d0 Fix issues after perspective switch (#786)
59a8ca2 Implemented compare mode for RideMapWindow (#786)
733db9c Ignore dot folders on athlete open/backup/delete
951e5f3 Fix crash on invalid perspective filter
[publish binaries]
2024-01-06 20:03:41 -03:00
Joachim Kohlhammer
49cf6340a4 Upgraded Qwt to 6.2 (branch: qwt-multiaxes) (#4427)
This commit is based on https://github.com/GoldenCheetah/GoldenCheetah/pull/3956
with the following additions / changes:
* Upgraded to the latest version of the multiaxes-branch, thus eliminating crashes of GoldenCheetah on startup
* Disabled the emitting of Layout Requests on geometry changes of QwtScaleWidget - without this, CPU utilization was up to 100% on one core
* Added the class SplineLookup, reusing small portions of code from Qwt 6.1
* Re-added the splines in WPrime and RideFile (resampling), using the new interface of QwtSpline
* Appveyor: qwt in cache-section now depends on qwt/qwtconfig.prin.in for refresh on version change
2024-01-06 18:59:55 -03:00
Alejandro Martinez
ea044a0c39 Accelerators are QKeySequence not tr strings
Continuation of b095b40
2024-01-06 17:15:33 -03:00
Alejandro Martinez
31636b196d Update Travis-ci macOS builds to xcode 14.2
[skip AppVeyor]
Related to #4093
2023-12-20 17:54:25 -03:00
jgpallero
c46a99e80e Update Spanish translation (#4426) 2023-12-17 08:48:20 -03:00
Alejandro Martinez
b6aefcc017 Fix some non-translatable strings and update ts files
Reported at the users forum by Jose Luis Garcia Pallero
2023-12-16 17:23:20 -03:00
Alejandro Martinez
edaac1486b Fix view in Calendar test chart
[skip ci]
From previous commit, lets default to Trends view
2023-12-15 20:39:22 -03:00
Alejandro Martinez
0116bb9e47 Add Calendar to test charts
[skip ci]
The old Calendar chart from Diary view,
it can be imported to v3.6 Analysis view.
2023-12-14 20:44:29 -03:00
Alejandro Martinez
707ed659b5 Add screen capture for ANT+ Pair
[skip ci]
2023-12-10 18:42:09 -03:00
Mark Liversedge
6c2a260b7e DataFilter - isAero
.. if a ride has sport "Aero" or has "AERO" xdata then it is
   identified as an aero ride file

.. isBike will now also check for isAero and return true, so
   you can record aero data but the ride is still treat as a
   bike ride in filters
2023-12-09 10:54:38 +00:00
Alejandro Martinez
f1a78f3fd3 Summary of changes from v3.6 release:
a3760bb Upgrade Travis-ci builds to macOS 12.6
6b1dbf4 Added Bluetooth pairing to the device wizard (#4422)
c0c8f57 Update FIT SDK definitions to 21.126 (#4423)
0dd4bf6 Cursor in text workout editor was invisible
6e5b950 Fix crash on metadata config
1dd7faa Interval Metadata
d9abb58 Datafilter xdataseries(), xdataunits() and xdatavalues()
5fb3bbf FIT parser bounds check when adding new series
943deb6 Generic Support for Session and Lap in FIT files
146f9ea Fix Weekly tiles in default Trends layouts
ec0653f ErgFilePlot - realtime curves honor FFWD/RWND and lap F/B
43368ad Mapview: Added interactivity to the Smallplot (#4408)
72de6bb Fix lap data auto-reset in slope workouts
c2f440c Fix broken workout directory check for the first start (#4410)
b095b40 Fix shortcuts not available due to translations
e6ff1a1 Python Chart Editor Cosmetics
00e182c Better user experience when drawing segments on the map (#4403)
f746f73 GPX parser - support ns3 TrackPointExtension name
9ae7521 Upgrade Travis-ci macOS version to macOS 11.6
e8132b1 Upgrade Travis-ci Linux version to Ubuntu 20.04
8f2ba0e Special case Start Date and Time in the cache
110652b Update German translation
fabc344 Add Wahoo PowrLink
f783814 Train library - add path to the list of possible errors
48d91d0 Fix issues after perspective switch (#786)
59a8ca2 Implemented compare mode for RideMapWindow (#786)
733db9c Ignore dot folders on athlete open/backup/delete
951e5f3 Fix crash on invalid perspective filter
[publish binaries]
2023-12-02 10:58:34 -03:00
Alejandro Martinez
bd4bed1f0e Upgrade Travis-ci builds to macOS 12.6
For testing #4093 and #4422, besides to be
the oldest still supported version
2023-12-02 10:58:23 -03:00
enngq11k
6b1dbf40f4 Added Bluetooth pairing to the device wizard (#4422)
* Added Bluetooth pairing to the device wizard

The wizard will now search (but not connect) for available Bluetooth
devices. The result is a simple list with all device names. The user can
now choose the desired devices in a multi select list and save them as a
"allow list" in the global training mode configuration. If no device is
selected, the profile will use the old behaviour and the connect button
searches for available devices.

* Fixed allow list check and extracted check into its own method

* Allow all devices if allow list is empty

* Selecting "No sensors found..." did create an invalid Bluetooth allow list (;;) which denied all devices

Added checks for a valid Bluetooth configuration for saving and loading.

* Remove separator from display name

If a user (some devices allow custom names) or a vendor uses ';' or ','
in the display name, we will replace them. We identify devices by MAC
or UUID, so this does not break the allow list. The display name is
stored for easy identification by users and following features

Fix #4318
2023-12-02 10:21:39 -03:00
Poncho
c0c8f57a13 Update FIT SDK definitions to 21.126 (#4423) 2023-12-01 09:44:36 -03:00
enngq11k
0dd4bf6816 Cursor in text workout editor was invisible
Changed the background to a lighter color to get the cursor visible again. To achive a good contrast, the text color for the selected line is now black. This combination works for dark and light mode.
2023-11-28 08:25:12 +00:00
Mark Liversedge
6e5b950f39 Fix crash on metadata config
.. add field got interval checkbox index wrong (I had already
   fixed this but was lost from commit)
2023-11-27 18:45:59 +00:00
Mark Liversedge
1dd7faa276 Interval Metadata
You can define metadata fields with
* indicator it is interval specific
* expression to disable/enable the field

Metadata configuration is updated on upgrade to
include a couple of new interval specific fields
just to get the user started (if interval specific
fields already exist this is skipped).

If the user does not maintain interval specific
data it will not be stored in saved Json files.

Within the metadata chart if a field is defined as
being interval related then an interval selector will
be shown at the top of that tab. When intervals are
selected in the sidebar the selection is also changed.

Interval tags are stored in the RideFileInterval to avoid
linking and tracking changes to interval info like name, start
and so on. This is therefore separate from the current practice
of storing general tags in the RideFile class.

Along the way I fixed rideitem opening the ride itself before emitting
the signal rideselected- since some functions that process the ride
selected will not neccessarily reference via RideItem::ride() before
working with metadata and intervals.

Interval metadata is written to the TAGS in a Json file with a name
of "<interval name>##<field name>" and openRideFile post processes
metadata read from the TAGS and places into the relevant
RideFileInterval.

NOTE: This is experimental and likely contains some bugs, the expression
added to a field definition is also not yet implemented.

Fixes #4418
2023-11-27 16:49:43 +00:00
Mark Liversedge
d9abb58209 Datafilter xdataseries(), xdataunits() and xdatavalues()
.. New datafilter functions to help access generic XDATA

   xdataseries("LAP") - returns list of all series
   xdataunits("LAP") - returns list of all units
   xdatavalues("LAP") - returns values in sequence suitable
                        for use with overview tiles
2023-11-17 15:42:34 +00:00
Mark Liversedge
5fb3bbfbbf FIT parser bounds check when adding new series
.. needs to be less than XDATA_MAXVALUES
2023-11-10 18:40:38 +00:00
Mark Liversedge
943deb67ea Generic Support for Session and Lap in FIT files
GENERIC SUPPORT FOR PARSING INTO XDATA

.. Generically parse FIT file messages into XDATA. The current
   implementation does this for session, lap and totals messages
   but could very easily be extended to any other message type

.. Generic parsing uses metadata rather than hard coding the
   message and field types and so on

.. The FIT metadata (FITmetadata.json) has been expanded to
   include definitions of message types and all the standard
   fields within the message types

.. The existing hard-coded parsing remains to extract data
   and apply directly to ridefile samples and metadata. The
   generic parser simply adds additional tabs on the data
   view as XDATA so users can access it.

   CODE REFACTORING, COMMENTS AND BUG FIXES

.. At some point the code needs to be refactored as it is
   janky and needs to align with the rest of the codebase

.. Includes a mild refactor renaming some of the classes/structs
   and variables to reflect what they actually are, for example:

       FitFileReadState -> FitFileParser
       FitDefinition -> FitMessage

.. Added lots of code comments and re-organised the code
   into clear sections to help navigate what is a very
   cumbersome source file, this breaks git blame history
   but is worth the loss (you can checkout an earlier commit
   to do a full blame)

.. Changed debugging levels to be more helpful

.. Generally I did not change any code, but there were a
   couple of serious bugs that needed to be corrected:

      Field definitions gets the type wrong in a couple of
      places since the type is stored in the low 4 bits:
      type = value & 0x1F

      The decodeDeveloperFieldDescription function did not
      check for NA_VALUEs for scale, offset, native field

.. For less serious bugs I added FIXME comments throughout the code

Fixes #4416
2023-11-10 17:14:50 +00:00
Alejandro Martinez
146f9eabc5 Fix Weekly tiles in default Trends layouts
So they are consistent across all date ranges
Fixes #4413
2023-11-07 09:58:08 -03:00
Alejandro Martinez
15bafbd444 Update snapshot builds
Summary of changes from v3.6 release:
ec0653f81 ErgFilePlot - realtime curves honor FFWD/RWND and lap F/B
43368addf Mapview: Added interactivity to the Smallplot (#4408)
72de6bbee Fix lap data auto-reset in slope workouts
c2f440c1c Fix broken workout directory check for the first start (#4410)
b095b403b Fix shortcuts not available due to translations
e6ff1a157 Python Chart Editor Cosmetics
00e182c41 Better user experience when drawing segments on the map
(#4403)
f746f7361 GPX parser - support ns3 TrackPointExtension name
9ae7521e5 Upgrade Travis-ci macOS version to macOS 11.6
e8132b1a5 Upgrade Travis-ci Linux version to Ubuntu 20.04
8f2ba0e11 Special case Start Date and Time in the cache
110652bf4 Update German translation
fabc344aa Add Wahoo PowrLink
f78381466 Train library - add path to the list of possible errors
48d91d02d Fix issues after perspective switch (#786)
59a8ca231 Implemented compare mode for RideMapWindow (#786)
733db9cb1 Ignore dot folders on athlete open/backup/delete
951e5f360 Fix crash on invalid perspective filter
[publish binaries]
2023-11-04 10:19:31 -03:00
Alejandro Martinez
ec0653f81f ErgFilePlot - realtime curves use context->getNow()
like Workout Editor does to honor ffwd/rwnd and lap f/b
Fixes #4412
2023-11-01 17:01:50 -03:00
Joachim Kohlhammer
43368addf7 Mapview: Added interactivity to the Smallplot (#4408)
* Added a tooltip showing data about the current position (Altitude, Power,
  HR, Time)
* Added a marker to the map corresponding to the current mouse position
  (both Google and OSM)
* Changed scaling of the smallplot: Chart is now between lowest point and
  highest point instead of sea level and highest point
2023-11-01 11:15:56 -03:00
Alejandro Martinez
72de6bbee1 Fix lap data auto-reset in slope workouts
+ Lap Distance was wrong until the first lap due to currentLap
  not checking the lap lower bound.
+ Lap Time was not reset due to workoutLap being also modified in
  guiUpdate, so the newLap signal was never generated.
+ Additionally newLap slot remove duplicate functions called on newLap signal
  and moved counters reset to the signal handling slot.
Fixes #4411
2023-10-31 19:30:50 -03:00
enngq11k
c2f440c1c0 Fixed broken workout directory check for the first start (#4410)
Fix1:
appsettings->value default fallback "0" if no fallback value was given.
So a new GoldenCheetah installation will always use path "0" until a
workout directory was set in the settings.
We now use an empty string as fallback to get the condition working
again

Fix2:
Instead of using the athlete->home parent folder, the old code returned
the parent's parent folder. Until a workout directory was set in the
settings, the user had to navigate to the (hidden) athletes folder
everytime by hand.
2023-10-31 11:18:31 -03:00
Alejandro Martinez
b095b403bd Accelerators are QKeySequence not tr strings
Fixes #4409
2023-10-28 10:38:34 -03:00
Mark Liversedge
216a43c562 Update README.md
Formatting
2023-10-22 08:54:44 +01:00
Mark Liversedge
de52b30773 Update README.md
Mention measures and metadata features
2023-10-22 08:53:21 +01:00
Mark Liversedge
e6ff1a157a Python Chart Editor Cosmetics
.. when working with a light background the syntax highlighting
   renders the text almost impossible to read because it uses
   very light colors

.. additionally, when the colors/theme are changed the python
   editor does not reflect the change until a restart

.. we should likely apply the same changes to the datafilter
   editor in the user chart
2023-10-21 10:46:19 +01:00
Joachim Kohlhammer
00e182c413 Better user experience when drawing segments on the map (#4403)
* Increased the area in which points are searched when clicking / hovering a
  track, easing the process of starting segment creation and giving more
  precision while drawing
* Hovering the track when drawing segments is not blocked any more by highlighted
  segments / parts of the current segment (i.e. segments can be shrinked during
  creation)
Fixes #4394
2023-10-09 20:11:35 -03:00
Alejandro Martinez
f746f7361b GPX parser - support ns3 TrackPointExtension name
Used in files generated by Garmin Connect
Fixes #4397
2023-10-04 13:13:35 -03:00
Alejandro Martinez
47b9b9e28f Travis-ci macOS after_success cleanup
[skip AppVeyor]
From last commit, it works and is faster this way.
2023-10-02 11:24:19 -03:00
Alejandro Martinez
a6bf25d062 Travis-ci macOS builds - avoid hungup
[skip AppVeyor]
Running GoldenCheetah from the mounted dmg doesn't terminate
soon enough, lets avoid this for better diagnosis.
[publish binaries]
2023-09-30 10:17:26 -03:00
Alejandro Martinez
0d382dc3f2 Travis-ci macOS with staged qwt build
[skip AppVeyor]
To avoid the cancelation due to 50' limit
[publish binaries]
2023-09-24 20:43:53 -03:00
Alejandro Martinez
e46a1d4a18 Update snapshot builds
To test v3.6 building on currently supported OS versions:
* Windows 10 (no change here)
* macOS 10.14 changed to macOS 11.6
* Ubuntu 18.04 changed to Ubuntu 20.04
Additionally it contains a fix to possible crashes with invalid
perspective filters, some cosmetic fixes and a new feature:
- Compare mode is now available for the Map chart
Please stay with the release version unless you are willing to
collaborate with testing.
[publish binaries]
2023-09-24 13:29:51 -03:00
Alejandro Martinez
9ae7521e50 Upgrade Travis-ci macOS version
[skip AppVeyor]
To macOS 11.6
Upgrade D2XX drivers to supported versions
2023-09-23 21:13:18 -03:00
Alejandro Martinez
a904147b63 Revert "Travis-ci - Exclude libjpeg.so.8 from AppImage"
[skip AppVeyor]
This reverts commit bbaa3c9c3c.
It was a mistake, sorry.
2023-09-23 20:22:40 -03:00
Alejandro Martinez
bbaa3c9c3c Travis-ci - Exclude libjpeg.so.8 from AppImage
[skip AppVeyor]
It seems to provoke issues on Arch Linux based
on previous commit
2023-09-22 20:58:00 -03:00
Alejandro Martinez
e8132b1a55 Upgrade Travis-ci Linux versions
[skip AppVeyor]
Move to Ubuntu 20.04 with supported D2XX drivers
Hopefully fixes #4396
2023-09-19 21:11:30 -03:00
Alejandro Martinez
d98249cf1f Remove DEV from Windows installer 2023-09-14 14:22:17 -03:00
Alejandro Martinez
8f2ba0e11d Special case Start Date and Time in the cache
They are defined as metadata but stored in a different way.
Enables Start_Date and Start_Time in formulas to match autocompleters.
Fixes #4391
2023-09-14 13:12:40 -03:00
Alejandro Martinez
110652bf40 Update German translation
Fixes #4386
2023-09-09 09:52:16 -03:00
Damien Grauser
fabc344aac Add Wahoo PowrLink 2023-09-08 21:16:11 +02:00
Alejandro Martinez
f783814665 Train library - add path to the list of possible errors
It seems to be a common error, see #4393
2023-09-07 10:35:15 -03:00
Joachim Kohlhammer
48d91d02d1 Fixed issues after perspective switch (#786)
* Upgraded leaflet to 1.9.4
* Fixed the condition when chart must be set to blank
* Fixed the zoom-level for OSM when switching perspective for the first time
2023-09-06 15:46:01 +02:00
Joachim Kohlhammer
59a8ca2314 Implemented compare mode for RideMapWindow (#786)
* Multiple activities can be viewed on one map at the same time
* Implemented for OSM ang Google
2023-09-06 15:46:01 +02:00
Alejandro Martinez
69c2b447aa Add screenshots for Training options
[skip ci]
2023-09-06 10:41:47 -03:00
Alejandro Martinez
733db9cb16 Ignore dot folders on athlete open/backup/delete
Fixes #4392
2023-09-03 21:45:23 -03:00
Alejandro Martinez
951e5f360a DataFilter - Use errors member instead of global
Update errors member from DataFiltererrors on constructor
and use it in evaluate functions, since they can be used when
DataFiltererrors no longer corresponds to this expression.
Fixes #4384
2023-08-13 14:23:19 -03:00
Alejandro Martinez
bd224c8251 Revert "Trigger v3.6 builds with version string"
[skip ci]
This reverts commit 22f45f364f,
it was a temporary hack to include version string in regular commit.
2023-08-05 10:39:08 -03:00
Alejandro Martinez
22f45f364f Trigger v3.6 builds with version string
[publish binaries]
2023-08-05 10:36:55 -03:00
Mark Liversedge
0286802d1c RELEASE 3.6 BUILD TRIGGER
.. trigger build of release binaries

[publish binaries]
2023-08-05 12:24:25 +01:00
Mark Liversedge
925445a215 VERSION 3.6 RELEASE
.. final release of version 3.6
2023-08-05 10:02:09 +01:00
Alejandro Martinez
511456bacd Update snapshot builds
To test latest changes before release
[publish binaries]
2023-07-30 13:39:32 -03:00
Alejandro Martinez
28f623b517 Preserve current layout as Legacy perspective
appending default perspectives for the view.
Fixes #4363
2023-07-03 15:16:57 -03:00
peret2000
4931ad1bd7 Upgrade Python AppImage version for Linux builds (#4375)
Python 3.7.16 AppImage is no longer available, upgrade to 3.7.17
2023-06-27 19:56:22 -03:00
Alejandro Martinez
7173437ab2 Update FIT SDK definitions to 21.115 2023-06-22 20:03:43 -03:00
dconka
14cb588f55 Update nongarmin.json (#4373)
Add new SIGMA ROX 12.1 EVO
2023-06-22 19:57:59 -03:00
Alejandro Martinez
2934bfe3bd Update German translation
Contributed by Marcen at the users forum
2023-06-20 17:45:51 -03:00
Mark Liversedge
dc3436dc65 Update README.md
.. OS X is now called MacOS (bit late to this one)
2023-06-08 15:24:10 +01:00
grauser
190aca8a73 Avoid double warning message 2023-06-07 22:47:07 +02:00
Mark Liversedge
6ef1cb7b96 Update README.md
.. include references to community sharing via cloud db
   open data and erg db

[skip ci]
2023-06-05 10:37:13 +01:00
Mark Liversedge
169c23ee58 Update README.md
.. more informative description with more fact based 
   statements and less emotive or hyperbolic language

[skip ci]
2023-06-05 10:31:26 +01:00
Mark Liversedge
7bf96285e7 Update README.md
.. screenshot instead of icon for github readme

[skip ci]
2023-06-05 10:06:28 +01:00
Mark Liversedge
067696aafd Screenshot for README.md
... Rather than the GC icon, lets put a screenshot of the app on the github
    welcome page for the repo

[skip ci]
2023-06-05 10:02:33 +01:00
peret2000
b07a7ef491 Use bicycle weight in Virtual Speed while training (#4365)
When computing virutalspeed based on slope, altitude, etc, total weight is relevant, specially in up and down hills

It was using 10kg plus the athlete weight. Now, it considers configured bicycle weigth. Not very relevant, but consistent with the data GH has for training
2023-06-04 17:05:02 -03:00
Mark Liversedge
7a1d99fca9 Refresh snapshot builds
.. last MacOS snapshots has an issue with the version of
   QT used and font matching which was fixed via a new commit.

[publish binaries]
2023-06-03 09:12:45 +01:00
Mark Liversedge
8b3dbbca7b Python 'printd' debug output strings not wide
.. we cannot pass wide strings to the 'printd' debug macro
   since it uses printf not wprintf. Not a major problem
   in this case since it is just a debug statement.

   introduced in previous commit that fixed crashes
   when embedding python v3.11 or higher
2023-06-01 09:12:58 +01:00
Poncho
e0a198a164 Fix python embedding crash with Python 3.11
.. use of standard strings instead of wide strings.

Fixes #4362
2023-05-31 21:14:11 +01:00
Mark Liversedge
f965345abc MacOS default font scaling smaller
.. for numerous reasons the font scaling on MacOS should be slightly
   less than for other platforms to be in keeping with the native
   systems font selections
2023-05-30 12:24:32 +01:00
Mark Liversedge
9b88abdeee Search QFontDatabase for installed fonts
.. instead of trying to create a font and use exactMatch()

.. this is faster and also avoids a qt-bug on MacOS for
   QFont::exactMatch() that keeps recurring
2023-05-30 08:28:49 +01:00
Alejandro Martinez
a37e27770c Update snapshot builds
For testing new default appearance settings
[publish binaries]
2023-05-28 18:20:46 -03:00
Mark Liversedge
228e2f24f9 Better fallback font sets
.. more likely to find Clear Sans and PT Sans on Linux
   and Mac respectively. Should avoid the dreaded Arial.
2023-05-28 17:17:42 +01:00
Mark Liversedge
93f8599070 Weird issue with QString arguments
.. fixed but not really sure why there was a problem
2023-05-27 12:04:53 +01:00
Mark Liversedge
7447af7053 About dialog show UI info
.. what dpi scaling and font size are we using. helpful for
   understanding how the ui is reacting to different resolutions
   and OS specific settings for scaling
2023-05-27 11:37:47 +01:00
Mark Liversedge
922c5e6985 Default Appearance Settings 2 of 2
.. default font scaling wasn't working (it was always 1.0). This is
   now fixed and means fonts are scaled so that GC always looks the
   same.

   For some users the fonts will appear too large, in this case they
   can reduce the font scaling to suit their own preferences.
2023-05-27 09:55:45 +01:00
Mark Liversedge
8a5bbc276f Fixup MacOS compiler error
.. last commit broke MacOS build and also left an errant debug
   statement in there for good measure
2023-05-26 13:23:04 +01:00
Mark Liversedge
c97efc1e49 Preferences reset appearances
.. a button on the config dialog to reset appearance settings
   to default values. Will be useful when fonts go squiffy
   of the user changes the resolution of their display.
2023-05-26 10:42:35 +01:00
Mark Liversedge
c01797b422 Minor fixup for default appearance recent commit
.. missing header broke build on MacOS

.. default width for mainwindow corrected
2023-05-25 11:24:26 +01:00
Mark Liversedge
47688ba754 Font fallback list use QString not char *
.. since initialising the array from strings is not supported
   in c++11 and causes a compile time error on Windows
2023-05-25 09:33:43 +01:00
Mark Liversedge
c97eac67a2 Default Appearance Settings 1 of 2
.. The default appearance settings on new install or directly
   after and upgrade are terrible and create a poor impression
   for new users

.. This commit fixes up scaling, font selection and themes so
   that for a new install or directly after upgrade they are
   set to defaults that are sensible for the current release

.. It is expected that these defaults will change and extend as
   we implement new features and the UI evolves- so these should
   be used as a basis for defaulting in the future.

.. A second update is required to resolve issues with scaling in
   overview charts dependant upon the screen resolution
2023-05-25 08:44:43 +01:00
Poncho
1a39471ad6 src/Python/PythonEmbed.cpp: forward python errors to the console (#4359) 2023-05-14 12:19:34 -03:00
Paul Johnson
0bf39ec4dd Stop batch processing entries from being edited (#4356) 2023-05-14 12:18:28 -03:00
Alejandro Martinez
103c87c600 Deprecate NewMainWindow
Complements fc3de5f
2023-04-22 21:13:34 -03:00
Alejandro Martinez
a3873a30fe Deprecate GProgressDialog
It was used only by the also deprecated MetricAggregator
2023-04-22 20:15:49 -03:00
Alejandro Martinez
efe64d3a96 Biweekly snapshot builds
Cumulative changes from v3.6-RC4
dbd33465c Update FIT SDK to 21.105
708d8744f Support larger font scaling
c85dab80a Skip previously imported files on Auto-Import (#4347)
1ecc6f9ec Python - Add compare support to activity series (#4349)
f0c9f12b4 FitRideFile - Identify Pulse Ox field
ab337f165 WorkoutWizard - Remove references to FTP and CP60
00d09af48 Highlight current selection in Train and Trends (#4320)
e7b9275a3 Update Italian translation
fdb35bf74 Athlete tab colour fix (#4257)
e32eabc10 Update German translation
[publish binaries]
2023-04-15 18:55:20 -03:00
Alejandro Martinez
dbd33465c4 Update FIT SDK to 21.105 2023-04-14 20:02:39 -03:00
Mark Liversedge
708d8744f6 Support larger font scaling
.. as 8k displays become more popular and affordable we need to
   support greater font scaling - we now scale up to x5 the
   default font size

   This should be good for devices well over 8k resolution but
   does highlight some limitations with Qt widgets and maximum
   sizes they support internally.
2023-04-13 11:01:11 +01:00
Alejandro Martinez
c85dab80a8 Skip previously imported files on Auto-Import (#4347)
If the importable file (after export when inside a .zip/.gz archive)
is present in imports files it means it was previously imported,
so it is skipped on Auto-Import for better performance and to avoid
re-appearance of deleted activities still present in the source folder.
Fixes #3696
Fixes #1892
2023-04-12 10:28:24 -03:00
Alejandro Martinez
1ecc6f9ec9 Python - Add compare support to activity series (#4349)
All activity functions working with data series,
both standard and xdata, now include an optional
compareindex=-1 parameter.
When compare mode is enabled compareindex parameter
is used as an index to get data for the corresponding
compare item, be an activity or an interval.
Sample chart contributed by Marcen at the users forum
Fixes #4346
2023-04-11 18:06:39 -03:00
Alejandro Martinez
26bf31a3d6 Biweekly snapshot builds
Just a few changes from RC4:
- Updated German, Italian and Spanish translations
- Better contrast in Athlete Tabs when using dark colors
- Better contrast for selected items in Trends/Train sidebar
  when using dark colors
- Clarify texts in Relative Wattage Workout Creator
[publish binaries]
2023-04-01 10:29:25 -03:00
vlcvboyer
97d5c896bd Code clean out (removing few warnings from build log) (#4331)
* Use wchar when 2 bytes charachers are used
* Mark provisional parameters as UNUSED
* Static cast OR select appropriate data type
* Fill up comment with missing parameter
---------
Co-authored-by: Alejandro Martinez <amtriathlon@gmail.com>
2023-03-29 19:36:46 -03:00
Alejandro Martinez
f0c9f12b44 FitRideFile - Identify Pulse Ox field
Generated by Garmin Health Snapshot activity.
Fixes #4344
2023-03-28 21:28:18 -03:00
Alejandro Martinez
ab337f165a WorkoutWizard - Remove references to FTP and CP60
Workouts are scaled using CP in GoldenCheetah.
2023-03-26 12:59:19 -03:00
Alejandro Martinez
1ae41e576a Revert "Workout Wizard - Honor Use CP as FTP setting"
This reverts commit 0767a98d0d.
My former interpretation was wrong, Workout Editor only
uses FTP for Coggan metrics, scaling uses CP.
2023-03-25 18:56:13 -03:00
Alejandro Martinez
0767a98d0d Workout Wizard - Honor Use CP as FTP setting
Like Workout Editor does, it is confusing otherwise.
2023-03-25 10:54:33 -03:00
vlcvboyer
00d09af489 Highlight current selection in Train and Trends (#4320)
Change on select bg and fg colors for Trends and Train,
currently are barely/no noticeable on Windows and macOs
when using dark colors.
---------
Co-authored-by: Alejandro Martinez <amtriathlon@gmail.com>
2023-03-25 10:33:46 -03:00
Alejandro Martinez
e7b9275a36 Update Italian translation
Contributed by Giuseppe Cifelli at the users forum.
2023-03-24 10:05:27 -03:00
Mark Liversedge
fc10661541 Revert SearchBox styling updates
.. the original behaviour is reverted, which is not ideal but
   does not cause rendering issues on Linux/MacOS and is compatible
   with searchbox usage on dialog widgets.

.. any updates to the toolbutton styling will need to consider
   a) placement on toolbar and dialog widgets
   b) platform specific considerations across Linux/Windows/MacOS
2023-03-24 09:44:05 +00:00
Mark Liversedge
536057bf66 Fixup Search/Filter Toolbutton on Linux
.. at least its fine on Linux, but need to consider how these
   changes have impacted MacOS separately.
2023-03-24 09:16:51 +00:00
Paul Johnson
fdb35bf74e Athlete tab colour fix (#4257)
* Corrects Athlete QTabBar tab colours to match NewSideBar,
  abstract on select background color selection from NewSideBar
  to Colors for reuse in MainWindow
* Fixes dropMenu visibility within the Filter/Search Box on Dark Themes
---------
Co-authored-by: Alejandro Martinez <amtriathlon@gmail.com>
2023-03-23 20:01:46 -03:00
Alejandro Martinez
e32eabc102 Update German translation
Contributed by Marcen at the users forum
2023-03-22 13:26:10 -03:00
Alejandro Martinez
985710a828 Update v3.6-RC4 builds
Fixes AZUM secret and Batch Processing localization issues
[publish binaries]
2023-03-21 10:30:07 -03:00
Alejandro Martinez
1aa166bea1 Patch Secrets.h with AZUM secret
Missing from previous commit
2023-03-20 22:01:47 -03:00
Alejandro Martinez
884cfef788 Update translation files for BatchProcessingDialog 2023-03-20 20:19:59 -03:00
Alejandro Martinez
02ad9767e2 BatchProcessingDialog - Fix localization errors
- DataProcessor primary key is english name,
  but localized name is displayed in combobox
- tr() macro only works on string constants
- make all messages translatable
- remove unused messages
2023-03-20 20:19:02 -03:00
jgpallero
574c8005c3 Spanish translation update (#4342) 2023-03-20 13:44:41 -03:00
Alejandro Martinez
b907e7f0a6 V3.6 RC4 BUILD
Trigger v3.6 RC build.
[publish binaries]
2023-03-18 13:38:09 -03:00
Mark Liversedge
29f59e3e24 Fixup MacOS compile error
.. missing header for QMessageBox
2023-03-17 18:50:15 +00:00
Alejandro Martinez
36cb446810 Update translation files
to include strings in BatchProcessing dialog.
2023-03-17 13:45:36 -03:00
Alejandro Martinez
6bf7781aea Change running Python DPs from Edit menu
To better match the new BatchProcessing dialog
- Python DPs are listed together with builtin processors
  to be executed like parameterless built in DPs, with
  option to cancel.
- They also appear under the Python Fixes submenu, but in
  this case they also can be edited.
2023-03-17 13:40:19 -03:00
Paul Johnson
add0f301e9 Batch processing (#4226)
Batch Processing - Delete, Data Processors & Export

Extension of Batch Export dialog to include other operation on multiple activities:
- run data processor (Builtin or Python)
- delete (after confirmation)

Co-authored-by: Alejandro Martinez <amtriathlon@gmail.com>
2023-03-17 13:01:48 -03:00
Alejandro Martinez
c77b32efaa Azum - Update Client ID and Secret 2023-03-16 15:28:29 -03:00
Alejandro Martinez
3aed45e96b FilterHRV - don't assume current activity
Fixes use from formulas and Python fixes
2023-03-14 13:07:26 -03:00
Alejandro Martinez
392ec2a74a Add Azum secret for AppVeyor builds 2023-03-13 11:49:46 -03:00
DanielZelei
2fc0c1d9ca Disable Azum logging 2023-03-13 09:08:53 +00:00
DanielZelei
dae573c939 Add optional user key to the Azum cloud provider 2023-03-13 09:08:53 +00:00
DanielZelei
0f5ec45308 Azum - disable logging 2023-03-13 09:08:53 +00:00
DanielZelei
a808b68ad7 Add new cloud service provider - Azum 2023-03-13 09:08:53 +00:00
Alejandro Martinez
5c0eb9910b Fix Travis-ci Linux build
[skip AppVeyor]
Copy sip.h to default Python include directory.
[publish binaries]
2023-03-05 20:08:34 -03:00
Alejandro Martinez
67136b3cdf Enable Python DPs use Metadata in automatic mode (#4336)
Data Processors running on import are applied before the activity
is added to RideCache and metrics are computed, this behavior is
by design, likely to optimize resource usage on bulk import.
So activityMetrics API is not available; a new getTag API was
added for this case and setTag/delTag/hasTag changed to work
in this context too.
When the Python fix is executed on activities already in the cache
either via Edit menu, Filters or other Python Fix changes are
notified via the corresponding RideItem.
Fixes #4095
[publish binaries]
2023-03-05 16:26:25 -03:00
Alejandro Martinez
42c43c7689 Fix Data Processors running on save after import
Currently they are ignored since applied to a RideFile
object immediatly discarded.
Changed to mimic behavior of CloudServices.
2023-03-05 13:16:02 -03:00
Alejandro Martinez
97570efdd2 Revert "Disable automatic execution of Python Data Processors"
This reverts commit 0d979f9fb9.
2023-03-01 21:25:15 -03:00
Alejandro Martinez
9b10f73422 Revert "Disable execution of Python DPs from formulas and Python API"
This reverts commit 434580ee81.
2023-03-01 21:22:32 -03:00
Alejandro Martinez
92963c8c83 Update default ODPM and WKO4 charts
Use the newly added timestring to format TTE
2023-02-27 13:06:24 -03:00
Alejandro Martinez
0e8fe3f9c9 Performance Tests - Add images for the wiki
[skip ci]
Contributed by Marcen at the forum
2023-02-27 11:33:06 -03:00
Alejandro Martinez
f2f519c44c New images for the wiki
[skip ci]
Contributed by Marcen at the forum
2023-02-19 22:10:16 -03:00
Alejandro Martinez
5f759c0b31 TabBar Chart Menu - image for the wiki
[skip ci]
Contributed by Marcen at the users forum
2023-02-18 16:21:30 -03:00
Alejandro Martinez
64907a3d2b Update CP Chart image for the wiki
[skip ci]
Contributed by Marcen at the users forum
2023-02-17 10:48:21 -03:00
Mark Liversedge
4e3e82655e Datafilter - double(p1) coerce to numeric
.. we already had string(p1) to coerce to string values but
   somehow forgot to do the reverse.
2023-02-13 08:54:36 +00:00
Alejandro Martinez
528259db3e Biweekly snapshot build
[publish binaries]
Cumulative changes from RC3
https://github.com/GoldenCheetah/GoldenCheetah/compare/v3.6-RC3...13167e0
2023-02-12 19:12:46 -03:00
Alejandro Martinez
13167e021c CP Chart - Add Delta Compare to standard settings
It was available only via reveal controls,
which are disabled in v3.6.
Fixes #4256
2023-02-07 22:07:57 -03:00
vlcvboyer
0904ebe1e0 Train - Accept gpx as videosynch source (#4329)
Fixes #4330
2023-02-06 12:48:42 -03:00
Alejandro Martinez
984f1f9d99 Fix German Translation
Contributed by Marcen at the users forum.
2023-02-02 20:13:33 -03:00
Alejandro Martinez
7c05a7f895 Update German Translation
Contributed by Marcen at the users forum
2023-02-02 16:04:20 -03:00
Alejandro Martinez
dda82c9a62 Images for the wiki - Overview Tiles for Trends
[skip ci]
Contributed by Marcen at users forum
2023-01-30 10:48:40 -03:00
Alejandro Martinez
dd8f8ebdce Images for the wiki-Overview Tiles for Activities
[skip ci]
Contributed by Marcen at users forum
2023-01-30 10:42:12 -03:00
Alejandro Martinez
ee65609143 Revert "New screen captures for the wiki - Overview Tiles for Activities"
[skip ci]
This reverts commit fb013c63e2.
Spaces in filenames are a PITA in github, will add them
again with underscores
2023-01-29 21:03:04 -03:00
Alejandro Martinez
84afd26262 Revert "New screen captures for the wiki - Overview Tiles for Trends"
[skip ci]
This reverts commit 7b7de8463b.
Spaces in filenames are a PITA in github, will add them
with underscores
2023-01-29 21:01:57 -03:00
Alejandro Martinez
7b7de8463b New screen captures for the wiki - Overview Tiles for Trends
[skip ci]
Contributed by Marcen at users forum
2023-01-29 20:19:45 -03:00
Alejandro Martinez
fb013c63e2 New screen captures for the wiki - Overview Tiles for Activities
[skip ci]
Contributed by Marcen at users forum
2023-01-29 20:17:15 -03:00
Alejandro Martinez
54d388c2a3 Update screen captures to v3.6 for the wiki
[skip ci]
Contributed by Marcen at the users forum
2023-01-29 20:14:19 -03:00
Alejandro Martinez
11decfc508 Biweekly snapshot build
[publish binaries]
Cumulative changes from RC3
402edf5 Stop signal processing during resetPerspective()
64386bc Perspective Selector Sync on switch Athlete tabs
b6fae05 Revert "Keep Perspective Selecto synced when switching athletes"
9eb8138 Revert "Fix strange behaviour when changing views"
0ddea94 Fix strange behaviour when changing views
88246a8 Overview Chart - Update metric pointer in tiles config
46bfab5 Overview - Use sport instead of isRun/isSwim
663bde0 Update Spanish translation (#4322)
30895b0 Update translation files to include latest strings
af21c35 FIT Files - Update sport list and sub sports (#4315)
68c7954 Add test FIT file from Garmin 945 swim with RR data
dfe572c Collect R-R data from Garmin HRM swim (#4319)
ef0eac8 Estimator - Use normalized Sport names
9531acf Remove Garmin devices already included in latest FIT SDK
523d2d1 Update FITmetadata.json to FIT SDK 21.94
bfa4b4b DataFilter - Metric aggretation honors AggregateZero and Count
c65f313 Revert "DataFilter - use RideCache::getAggregate continuation"
e95d116 DataFilter - Avoid crashes when no ride is selected
3c3d202 Fix DataFilter use of PowerIndex
cc5eaf4 Estimates and Performances - Generalize to any sport with power data (#4307)
abb69b8 DialWindow - Fix rolling average initialization
841766e DataFilter - use RideCache::getAggregate continuation
afbb43e DataFilter - asaggstring uses RideCache::getAggregate
33ba1c0 FitRideFile - Avoid crashes on multi-sessions from CloudServices
018bd40 FTMS: Add support for Spin Down Calibration (#4073)
4f97bae DOB - display using 4 digits year
dfeb853 macOS plist - Add required BTLE keys for newer versions
2a99c87 Python 3.7.15 AppImage is no longer available, upgrade to 3.7.16 (#4299)
0296693 Workout Chart - Imperial units support (#4232)
8919eab Map Chart - Update default Tile Servers
7d0e6de Bug Fixes for live map base url and remove erroneous debug message (#3901)
1c5bbec Train - Improve L/R Balance Dial display
8e0b0a6 R/Python API - Sport case insensitive in Athlete Zones
b08e662 Train - Show lap notifications only when available
2c3eabd RideCache - Fix refresh to inclu=de the oldest activity
9c7d1d4 Strava Sync - Tag simulation rides as VirtualRide
53f8f51 Fix memory leak in Python API - part 2
e477b05 ErgDB Download - Decode title to be used as name
3a16d1e Keep Perspective Selecto synced when switching athletes
63d13ba Update Italian translation
f947b6b VideoSync - Distance scaling only applies to CRS workouts
67962bf Fix memory leak in Python API
5f22d12 fix(doc): mention QMAKE_MOVE requirement for bison > 3.7
996ee63 Remove MapQuest API Key from gcconfig.pri.in
a7ad134 Measures CSV Import - Last field can be empty
90172a4 Replace Tracker in default Trends layout
68b70e0 Fix Elevation - Avoid 302 network error
434580e Disable execution of Python DPs from formulas and Python API
cb23914 Honor chart filters in Trends view Histogram and CP charts (#4287)
1941b9a Minimum bison version is now 2.7
2023-01-28 18:42:36 -03:00
Mark Liversedge
402edf51fc Stop signal processing during resetPerspective()
.. fixes undesirable behaviour with click thru on user charts

Fixes #4325
2023-01-28 17:44:51 +00:00
Mark Liversedge
64386bc1ba Perspective Selector Sync on switch Athlete tabs
.. when switching athlete tabs the perspective selector would
   always be reset to the first entry, this update makes sure
   we reset to the correct one.

Fixes #4325
2023-01-28 16:28:08 +00:00
Alejandro Martinez
b6fae05d48 Revert "Keep Perspective Selecto synced when switching athletes"
This reverts commit 3a16d1ecc2.
2023-01-26 15:31:58 -03:00
Alejandro Martinez
9eb81385e8 Revert "Fix strange behaviour when changing views"
This reverts commit 0ddea94b7a.
2023-01-26 15:31:29 -03:00
Alejandro Martinez
0ddea94b7a Fix strange behaviour when changing views
The problem was introduce by 3a16d1e, the change in perspectiveSelector
current index triggers currentIndexChanged when the view change has
not been finished, to avoid this we use activated signal and add
a check to do nothing when the index has not changed.
The problem was reported at the forum.
2023-01-26 12:06:37 -03:00
Alejandro Martinez
88246a8b15 Overview Chart - Update metric pointer in tiles config
When metric selection changes in tiles config the metric
pointer was not updated accordingly leading to inconsistencies
s.t. a Total metric displayed as an Average metric in Trends
until restart, since at tile creation the correct pointer is used.
2023-01-25 16:40:37 -03:00
Alejandro Martinez
46bfab5c8b Overview - Use sport instead of isRun/isSwim
It is simpler and more general to get activities from the same sport.
2023-01-24 20:37:03 -03:00
jgpallero
663bde04c5 Update Spanish translation (#4322) 2023-01-23 11:22:08 -03:00
Alejandro Martinez
30895b028d Update translation files to include latest strings 2023-01-23 09:43:12 -03:00
vlcvboyer
af21c35022 FIT Files - Update sport list and sub sports (#4315)
* move sports list in a function for other calls
* Decode sport and sub-sport and push into activity tag
* Remove inaccurate comments
* Populate additional sports ID from documentation
* use of standardized RideFile::sport()

Fixes #4312
Fixes #4313
2023-01-21 18:58:30 -03:00
Alejandro Martinez
68c795440c Add test FIT file from Garmin 945 swim with RR data
[skip ci]
2023-01-20 20:58:53 -03:00
vlcvboyer
dfe572c005 Collect R-R data from Garmin HRM swim (#4319)
Fixes #4024
2023-01-20 20:51:16 -03:00
Alejandro Martinez
ef0eac8908 Estimator - Use normalized Sport names
Otherwise Rowing will not match Row activities, for example.
Continuation of cc5eaf4
2023-01-18 21:29:05 -03:00
Alejandro Martinez
9531acf366 Remove Garmin devices already included in latest FIT SDK 2023-01-18 21:27:39 -03:00
Alejandro Martinez
6f6d7c6a8f Biweekly snapshot build update
[publish binaries]
Cumulative changes from RC3
523d2d1 Update FITmetadata.json to FIT SDK 21.94
bfa4b4b DataFilter - Metric aggretation honors AggregateZero and Count
c65f313 Revert "DataFilter - use RideCache::getAggregate continuation"
e95d116 DataFilter - Avoid crashes when no ride is selected
3c3d202 Fix DataFilter use of PowerIndex
cc5eaf4 Estimates and Performances - Generalize to any sport with power data (#4307)
abb69b8 DialWindow - Fix rolling average initialization
841766e DataFilter - use RideCache::getAggregate continuation
afbb43e DataFilter - asaggstring uses RideCache::getAggregate
33ba1c0 FitRideFile - Avoid crashes on multi-sessions from CloudServices
018bd40 FTMS: Add support for Spin Down Calibration (#4073)
4f97bae DOB - display using 4 digits year
dfeb853 macOS plist - Add required BTLE keys for newer versions
2a99c87 Python 3.7.15 AppImage is no longer available, upgrade to 3.7.16 (#4299)
0296693 Workout Chart - Imperial units support (#4232)
8919eab Map Chart - Update default Tile Servers
7d0e6de Bug Fixes for live map base url and remove erroneous debug message (#3901)
1c5bbec Train - Improve L/R Balance Dial display
8e0b0a6 R/Python API - Sport case insensitive in Athlete Zones
b08e662 Train - Show lap notifications only when available
2c3eabd RideCache - Fix refresh to inclu=de the oldest activity
9c7d1d4 Strava Sync - Tag simulation rides as VirtualRide
53f8f51 Fix memory leak in Python API - part 2
e477b05 ErgDB Download - Decode title to be used as name
3a16d1e Keep Perspective Selecto synced when switching athletes
63d13ba Update Italian translation
f947b6b VideoSync - Distance scaling only applies to CRS workouts
67962bf Fix memory leak in Python API
5f22d12 fix(doc): mention QMAKE_MOVE requirement for bison > 3.7
996ee63 Remove MapQuest API Key from gcconfig.pri.in
a7ad134 Measures CSV Import - Last field can be empty
90172a4 Replace Tracker in default Trends layout
68b70e0 Fix Elevation - Avoid 302 network error
434580e Disable execution of Python DPs from formulas and Python API
cb23914 Honor chart filters in Trends view Histogram and CP charts (#4287)
1941b9a Minimum bison version is now 2.7
2023-01-17 18:59:11 -03:00
Alejandro Martinez
523d2d1909 Update FITmetadata.json to FIT SDK 21.94 2023-01-17 18:48:35 -03:00
Alejandro Martinez
bfa4b4b977 DataFilter - Metric aggretation honors AggregateZero and Count
When computing metric averages
2023-01-16 12:54:29 -03:00
Alejandro Martinez
c65f313de5 Revert "DataFilter - use RideCache::getAggregate continuation"
This reverts commit 841766effb
since it provokes crashes in some Trends Overview charts.
TODO: fix aggregation to consider AggregateZero and count
properties of metrics.
2023-01-15 21:44:56 -03:00
Alejandro Martinez
b689d29653 Biweekly snapshot build
[publish binaries]
Cumulative changes from RC3
e95d11671 DataFilter - Avoid crashes when no ride is selected
3c3d2024a Fix DataFilter use of PowerIndex
cc5eaf418 Estimates and Performances - Generalize to any sport with power data (#4307)
abb69b8fb DialWindow - Fix rolling average initialization
841766eff DataFilter - use RideCache::getAggregate continuation
afbb43edd DataFilter - asaggstring uses RideCache::getAggregate
33ba1c03e FitRideFile - Avoid crashes on multi-sessions from CloudServices
018bd404e FTMS: Add support for Spin Down Calibration (#4073)
4f97bae97 DOB - display using 4 digits year
dfeb8532a macOS plist - Add required BTLE keys for newer versions
2a99c8762 Python 3.7.15 AppImage is no longer available, upgrade to 3.7.16 (#4299)
0296693dd Workout Chart - Imperial units support (#4232)
8919eab5b Map Chart - Update default Tile Servers
7d0e6de0b Bug Fixes for live map base url and remove erroneous debug message (#3901)
1c5bbecf1 Train - Improve L/R Balance Dial display
8e0b0a67a R/Python API - Sport case insensitive in Athlete Zones
b08e662c9 Train - Show lap notifications only when available
2c3eabdd8 RideCache - Fix refresh to inclu=de the oldest activity
9c7d1d4f3 Strava Sync - Tag simulation rides as VirtualRide
53f8f5102 Fix memory leak in Python API - part 2
e477b05a9 ErgDB Download - Decode title to be used as name
3a16d1ecc Keep Perspective Selecto synced when switching athletes
63d13ba9e Update Italian translation
f947b6bd3 VideoSync - Distance scaling only applies to CRS workouts
67962bfff Fix memory leak in Python API
5f22d12a6 fix(doc): mention QMAKE_MOVE requirement for bison > 3.7
996ee63cd Remove MapQuest API Key from gcconfig.pri.in
a7ad1346e Measures CSV Import - Last field can be empty
90172a4a6 Replace Tracker in default Trends layout
68b70e0e4 Fix Elevation - Avoid 302 network error
434580ee8 Disable execution of Python DPs from formulas and Python API
cb23914a5 Honor chart filters in Trends view Histogram and CP charts (#4287)
1941b9af7 Minimum bison version is now 2.7
2023-01-14 19:38:19 -03:00
Alejandro Martinez
e95d11671a DataFilter - Avoid crashes when no ride is selected
This is an edge case, no ride available or no one selected,
but it can happens, so lets avoid the crash.
2023-01-14 10:29:42 -03:00
Mark Liversedge
3c3d2024ac Fix DataFilter use of PowerIndex
.. 3rd param is not required as it gets defaulted, and has
   recently changed from bool to QString

Fixes #4308
2023-01-14 10:50:37 +00:00
Alejandro Martinez
cc5eaf4187 Estimates and Performances - Generalize to any sport with power data (#4307)
Weekly estimates and performances are precomputed for any sport
with power data, not just Bike and Run.
In Trends view both LTM charts and DataFilter select sport based
on applied filters: when all activities are from the same sport,
that is used to select estimates and performances, otherwise
Bike estimates and performances are used for backward compatibility.
This reverts 1a285d1050
2023-01-13 14:58:05 -03:00
Alejandro Martinez
abb69b8fb5 DialWindow - Fix rolling average initialization
Reported in #4298
2023-01-11 19:40:29 -03:00
Alejandro Martinez
841766effb DataFilter - use RideCache::getAggregate continuation
This completes afbb43edd1
2023-01-03 16:19:03 -03:00
Alejandro Martinez
afbb43edd1 DataFilter - asaggstring uses RideCache::getAggregate
For consistency and simplicity, getAggregate honors AggregateZero
and count properties of metrics, beside some special cases.
Fixes #4302
TODO: aggmetric and aggmetricstrings likely have a similar problem.
2023-01-02 15:38:50 -03:00
Alejandro Martinez
33ba1c03ec FitRideFile - Avoid crashes on multi-sessions from CloudServices
CloudServices doesn't request for multi-sessions and a crash
happens when available.
Reported at the forum by CloudServices developer.
2022-12-29 09:30:11 -03:00
Alejandro Martinez
bb972b7e8a Biweekly snapshot build
[publish binaries]
Cumulative changes from RC3
018bd404e FTMS: Add support for Spin Down Calibration (#4073)
4f97bae97 DOB - display using 4 digits year
dfeb8532a macOS plist - Add required BTLE keys for newer versions
2a99c8762 Python 3.7.15 AppImage is no longer available, upgrade to 3.7.16 (#4299)
0296693dd Workout Chart - Imperial units support (#4232)
8919eab5b Map Chart - Update default Tile Servers
7d0e6de0b Bug Fixes for live map base url and remove erroneous debug message (#3901)
1c5bbecf1 Train - Improve L/R Balance Dial display
8e0b0a67a R/Python API - Sport case insensitive in Athlete Zones
b08e662c9 Train - Show lap notifications only when available
2c3eabdd8 RideCache - Fix refresh to inclu=de the oldest activity
9c7d1d4f3 Strava Sync - Tag simulation rides as VirtualRide
53f8f5102 Fix memory leak in Python API - part 2
e477b05a9 ErgDB Download - Decode title to be used as name
3a16d1ecc Keep Perspective Selecto synced when switching athletes
63d13ba9e Update Italian translation
f947b6bd3 VideoSync - Distance scaling only applies to CRS workouts
67962bfff Fix memory leak in Python API
5f22d12a6 fix(doc): mention QMAKE_MOVE requirement for bison > 3.7
996ee63cd Remove MapQuest API Key from gcconfig.pri.in
a7ad1346e Measures CSV Import - Last field can be empty
90172a4a6 Replace Tracker in default Trends layout
68b70e0e4 Fix Elevation - Avoid 302 network error
434580ee8 Disable execution of Python DPs from formulas and Python API
cb23914a5 Honor chart filters in Trends view Histogram and CP charts (#4287)
1941b9af7 Minimum bison version is now 2.7
2022-12-23 18:11:49 -03:00
Erik Botö
018bd404e8 FTMS: Add support for Spin Down Calibration (#4073)
Initial implementation - merged for testing since it seems to be safe.
2022-12-21 17:25:54 -03:00
Alejandro Martinez
4f97bae97d DOB - display using 4 digits year
To avoid issues like #2584
2022-12-21 13:28:38 -03:00
Alejandro Martinez
dfeb8532a9 macOS plist - Add required BTLE keys for newer versions
[skip AppVeyor]
According to https://bugreports.qt.io/browse/QTBUG-96557
Intended to fix #4093
2022-12-19 19:00:56 -03:00
peret2000
2a99c87620 Python 3.7.15 AppImage is no longer available, upgrade to 3.7.16 (#4299) 2022-12-19 08:34:03 -03:00
Peter Kanatselis
0296693ddd Workout Chart - Imperial units support (#4232)
Co-authored-by: Alejandro Martinez <amtriathlon@gmail.com>
2022-12-17 19:47:25 -03:00
Alejandro Martinez
8919eab5b2 Map Chart - Update default Tile Servers 2022-12-16 17:35:01 -03:00
Peter Kanatselis
7d0e6de0b1 Bug Fixes for live map base url and remove erroneous debug message (#3901)
Use default OSM tile server
Co-authored-by: Alejandro Martinez <amtriathlon@gmail.com>
2022-12-16 16:26:18 -03:00
Alejandro Martinez
1c5bbecf1c Train - Improve L/R Balance Dial display
Includes proper treatement for NA, switched L/R and
enables averaging.
Fixes #4298
2022-12-16 15:49:22 -03:00
Alejandro Martinez
8e0b0a67a6 R/Python API - Sport case insensitive in Athlete Zones
For backward compatibility with existing charts
2022-12-14 13:43:17 -03:00
Alejandro Martinez
b08e662c9d Train - Show lap notifications only when available
It is misleading otherwise.
2022-12-12 19:53:16 -03:00
Alejandro Martinez
5af234d6ad Biweekly snapshot build
[publish binaries]
Cumulative changes from RC3
2c3eabdd8 RideCache - Fix refresh to include the oldest activity
9c7d1d4f3 Strava Sync - Tag simulation rides as VirtualRide
53f8f5102 Fix memory leak in Python API - part 2
e477b05a9 ErgDB Download - Decode title to be used as name
3a16d1ecc Keep Perspective Selecto synced when switching athletes
63d13ba9e Update Italian translation
f947b6bd3 VideoSync - Distance scaling only applies to CRS workouts
67962bfff Fix memory leak in Python API
5f22d12a6 fix(doc): mention QMAKE_MOVE requirement for bison > 3.7
996ee63cd Remove MapQuest API Key from gcconfig.pri.in
a7ad1346e Measures CSV Import - Last field can be empty
90172a4a6 Replace Tracker in default Trends layout
68b70e0e4 Fix Elevation - Avoid 302 network error
434580ee8 Disable execution of Python DPs from formulas and Python API
cb23914a5 Honor chart filters in Trends view Histogram and CP charts (#4287)
1941b9af7 Minimum bison version is now 2.7
2022-12-11 13:13:14 -03:00
Alejandro Martinez
2c3eabdd8b RideCache - Fix refresh to include the oldest activity
This boundary error provokes the cache entry for the oldest
activity don't be refreshed on full cache refresh, only
when the activity is imported or opened (s.t. selecting it
in Activities View).
For most users this may be uneventfull, but if the oldest
activity becomes dirty, a full cache will happend on each
following start, until the oldest activity is opened and
it may explain the behavior reported ocasionally at the forum
and recently in #4297
2022-12-10 10:14:44 -03:00
Alejandro Martinez
9c7d1d4f31 Strava Sync - Tag simulation rides as VirtualRide
Also map Walking Sport to Walk activity type
2022-12-05 17:10:04 -03:00
Alejandro Martinez
53f8f5102c Fix memory leak in Python API - part 2
Py_buildValue does not steal references, leading to an incorrect
reference counter and therefore resources not freed by the
garbage collector.
Contributed by Joachim at the forum.
2022-12-03 12:07:06 -03:00
Alejandro Martinez
e477b05a98 ErgDB Download - Decode title to be used as name
Title is html encoded, we need to decode it for readability and,
since name is used as a filename, replace "/" by "-".
This still has some limitations s.t. duplicate titles, but they
have easy workarounds for the user and they don't justify to change
the database schema now in my POV.
2022-12-01 13:16:47 -03:00
Alejandro Martinez
3a16d1ecc2 Keep Perspective Selecto synced when switching athletes
Fixed error reported by Marcen in users forum
2022-11-30 10:27:10 -03:00
Alejandro Martinez
63d13ba9e5 Update Italian translation
Contributed by https://github.com/gicif
Fixes #4296
2022-11-29 16:57:59 -03:00
Alejandro Martinez
f947b6bd31 VideoSync - Distance scaling only applies to CRS workouts 2022-11-29 14:35:22 -03:00
Alejandro Martinez
67962bfff8 Fix memory leak in Python API
PyDict_SetItemString does not steal references, leading to an incorrect
reference counter and therefore resources not freed by the garbage collector.
Contributed by Joachim at the forum.
[publish binaries]
2022-11-28 14:33:49 -03:00
Christoph Hasse
5f22d12a61 fix(doc): mention QMAKE_MOVE requirement for bison > 3.7
[skip ci]
2022-11-20 19:46:15 -03:00
Alejandro Martinez
996ee63cd5 Remove MapQuest API Key from gcconfig.pri.in
It was deprecated and replaced by OpenElevation public API
[publish binaries]
2022-11-15 12:48:16 -03:00
Alejandro Martinez
a7ad1346e8 Measures CSV Import - Last field can be empty
Fixes #4292
2022-11-13 17:36:35 -03:00
Alejandro Martinez
90172a4a62 Replace Tracker in default Trends layout
It is now an Overview with a Table tile, original
LTM Tracker still available as a Library chart.
2022-11-10 12:17:56 -03:00
Alejandro Martinez
68b70e0e4d Fix Elevation - Avoid 302 network error
Even when the API is unlimited we get 302 error for longer rides,
lets avoid it breaking requests in smaller chunks.
2022-11-09 13:58:29 -03:00
Alejandro Martinez
434580ee81 Disable execution of Python DPs from formulas and Python API
Metadata and metrics don't work in these contexts as documented
in #4095 so we disable them to avoid confusion until the root
issue is solved.
Fixes #4288
2022-11-07 20:21:56 -03:00
Alejandro Martinez
cb23914a5f Honor chart filters in Trends view Histogram and CP charts (#4287)
Just appending the file lists doesn't work like addFilter
does, isfiltered and files are added as optional parameters
to Pespective:filterlist so they are accounted for when
the list of files is generated.
Fixes #4285
2022-11-01 18:29:34 -03:00
Alejandro Martinez
1941b9af7f Minimum bison version is now 2.7
[skip ci]
2022-10-30 12:16:46 -03:00
Mark Liversedge
67352f6dc2 V3.6 RC3 BUILD
.. trigger build of RC3

[publish binaries]
2022-10-29 20:23:56 +01:00
Alejandro Martinez
fa8eb0b6da DataFilter parser - remove warnings and avoid crash on syntax error
- Crash on syntax error happened on <leaf> destructor and the cause
  was tokens declared as <leaf> but not creating a leaf, to avoid
  this a new <string> type without destructor was added for them.
- Warnings indicated semantic value not set for some rules due to
  the lack of $$ = $1, likely bening, but lets avoid it.
2022-10-28 17:24:10 -03:00
Alejandro Martinez
5a77180957 Enable builds using bison 3.7 or higher
[skip ci]
Fixes #3586
2022-10-27 13:54:34 -03:00
Alejandro Martinez
50a027ad70 Update Italian translation
Contributed by https://github.com/gicif, Fixes #4283
2022-10-27 10:36:56 -03:00
Alejandro Martinez
a99cc3305e Datafilter - Add Compound case to Leaf::toString
For debugging and completenes
2022-10-26 18:01:01 -03:00
Alejandro Martinez
6f4da994a2 Strava download - avoid crashes when lap swim file has 0 lenght lap
Includes sample file from users forum
2022-10-26 11:20:43 -03:00
Alejandro Martinez
8946c53650 Update default Favourite Metrics
To include Time Recording, Time Moving and Running Cadence.
2022-10-25 20:53:51 -03:00
Alejandro Martinez
92ab04ac8a Upgrade bison to v2.7 for macOS builds on Travis-ci
[skip AppVeyor]
This is the minimum change to be able to use %destructor in
DataFilter.y, the same version is used for Windows builds.
2022-10-24 14:09:49 -03:00
Mark Liversedge
cfa767a854 VERSION 3.6 RC3 DEVELOPMENT BUILD
.. another release candidate prior to release

[publish binaries]
2022-10-23 11:51:54 +01:00
Alejandro Martinez
9af08b7f3c Release memory when DataFilter parsing fails
This is a continuation of 523ffcc, %destructor bison
directive is used to clean and delete Leaf nodes
allocated and discarded by the parser.
Hopefully fixes #4249
2022-10-22 17:22:23 -03:00
Alejandro Martinez
523ffcc702 Avoid crashes when DataFilter parsing fails
This started to happen after #4277, problem is when parsing fails
treeRoot can point ot non Leaf objects. This does not happens when
parsing from the DataFilter constructor since treeRoot is forced
to NULL on errors, this commit does the same for check and parseFilter.
Remaining problem is the memory leak in these cases, which are frequent
when editing filters in User or LTM charts as explained in #4249
2022-10-20 20:27:19 -03:00
peret2000
5c4f6e1f82 Upgrade Python AppImage version for Linux builds (#4281)
Python 3.7.14 AppImage is no longer available, upgrade to 3.7.15
2022-10-18 14:25:51 -03:00
Alejandro Martinez
761e0527a2 Change DataFilter lexer to process non ASCII string constants
Fixes #4278
2022-10-18 11:18:33 -03:00
Alejandro Martinez
fd3bab7e85 Add swimscore.pdf and govss.pdf to repository
[skip ci]
They are no available anymore from the original source
Fixes #4279
2022-10-18 10:43:41 -03:00
Alejandro Martinez
327150d659 Add DataFilter destructor calling clearFilter to release memory
The crash documented in #4249 was related to the conversion of
Leaf of type Symbol to Function when () are found afterwards.
This is fixed in this commit, but more testing is necessary to
see if there are other cases.
2022-10-16 15:58:37 +01:00
Alejandro Martinez
d5905d92d0 Leaf::clear - delete container elements after clear 2022-10-16 15:58:37 +01:00
Alejandro Martinez
10c2660f0b clearFilter - release memory avoiding crashes
clearFilter - delete root Leaf
Leaf constructor: initialize left,right and cond to null pointers
Leaf::clear avoid crashes when called with a null pointer parameter,
and release memory in all cases allocated in the parser
TODO: still crashes if called from DataFilter destructor, see #4249
2022-10-16 15:58:37 +01:00
Alejandro Martinez
82e79fa898 Disable Leaf::clear method to avoid crashes
Lets avoid crashes until #4249 is fixed
2022-10-09 10:46:22 -03:00
Alejandro Martinez
8860d5da08 Don't show the option to hide Activity labels in Options > Apperarance
Since it is commented out in RideNavigator.
TODO: cleanup if this is not useful anymore
2022-10-02 19:43:35 -03:00
Alejandro Martinez
746cea2d26 Add Preferences > Intervals image for the wiki
[skip ci]
2022-10-02 15:58:31 -03:00
jgpallero
edfc3ba642 Small syntax correction in Spanish translation (#4275) 2022-10-01 17:39:27 -03:00
Alejandro Martinez
a6338ee381 Update Share menu image for the wiki
[skip ci]
2022-10-01 10:58:18 -03:00
Alejandro Martinez
234bdb67e6 Add Equipment chart to default Trends layout
Contributed at the forum, it is a nice example of User Chart,
and it allows a general exploit of the Equipment data field.
2022-09-28 12:24:27 -03:00
Alejandro Martinez
b43723e8ff Use default Overview configuration when replacing old Summary charts
They are likely more useful for existing users and, hopefully,
they will produce less user complains than blank Summary charts.
2022-09-26 21:35:23 -03:00
Alejandro Martinez
6b15b7e50e kml files are not supported for import
Just as output files for Google Earth et. al.
Fixes #4271
2022-09-25 19:54:18 -03:00
grauser
7b64448912 fix(xert):name can be utf8
[publish binaries]
2022-09-15 14:15:11 +02:00
grauser
925d5c3521 fix(oauth):correct nolio secret param name
[publish binares]
2022-09-15 12:50:23 +02:00
Alejandro Martinez
0185080f3f Upgrad Python AppImage version for Linux builds
[skip AppVeyor]
Python 3.7.13 AppImage is no longer available,
upgrade to 3.7.14
[publish binaries]
2022-09-09 19:19:19 -03:00
Alejandro Martinez
3b528f8a12 Update VERSION36_BUILD and generate snapshots
Missing from RC2 build, also include the fix to avoid crashes when
myPerspective is not set in existing charts and default layouts
without R charts to avoid #4267 for newly create athletes.
[publish binaries]
2022-09-09 18:12:10 -03:00
Alejandro Martinez
56500cf357 R Chart API - Add missing constants 2022-09-08 10:21:42 -03:00
Alejandro Martinez
eca82afa4e Wiki - Remove old scope bar image 2022-09-08 10:20:58 -03:00
Alejandro Martinez
abde31ecc3 Wiki - Update UILayout_MainWindowElements image
[skip ci]
Contributed by Marcen at the users forum
2022-09-06 20:38:57 -03:00
Alejandro Martinez
1be14feb6d Wiki - Update Help Menu
[skip ci]
2022-09-06 14:12:37 -03:00
Alejandro Martinez
0d30d446f8 Avoid crashes if perspective is not set
Continuation of fbae10f
2022-09-06 10:18:46 -03:00
Alejandro Martinez
fbae10f103 Avoid crash in CP chart when perspective is not set
This was reported at the forum and it is reproducible with
the supplied home-perspectives.xml, it was likely generated
by an older version, but lets get defensive just in case.
2022-09-05 12:39:08 -03:00
Alejandro Martinez
cc6738bdf5 Remove R charts from default layouts
SS-RR and Tri Mix replaced by Python versions
contributed by Fe at the users forum.
The intention is to avoid triggering #4267
2022-09-05 11:51:44 -03:00
Alejandro Martinez
7d7ed5cfb3 Fix drag and drop to compare pane issues for v3.6
- DragDropMode is changed from InternalMove to DragDrop in RideTreeView,
  this enables compare of activities again
- DragDropMode is changed from InternalMove to DragDrop in SeasonTreeView,
  MoveAction is made the default action and dragEnterEvent ignores
  events other than move or from other origins. This avoids compared
  date ranges loosing their names.
- DragDropMode is changed from InternalMove to DragDrop in IntervalTreeView,
  MoveAction is made the default action and dragEnterEvent ignores
  events other than move or from other origins. This avoids removal
  of compared intervals from the intervals list.
This solution was contributed by Joachim at the users forum.
Fixes #3622
[publish binaries]
2022-09-03 11:17:28 -03:00
Alejandro Martinez
300960f234 Add Repository Search imgage for the Wiki
[skip ci]
2022-09-01 10:14:13 -03:00
Alejandro Martinez
b02b5f1265 Trends Sidebar - Don't process itemChanged event from date range tree
Items are not editable, so it is not used in the normal flow,
and it worsen a bug which clears the date range name in the item
when dropping on compare pane commiting the change to seasons.xml
2022-08-31 20:07:02 -03:00
Alejandro Martinez
80b671f4aa Update German Translation
Contributed by forum user Marcen
2022-08-29 19:00:17 -03:00
Alejandro Martinez
ef23cb5d1c Estimator - Add model identification to debug log 2022-08-29 13:28:01 -03:00
jgpallero
a212ff6408 Update Spanish translation (#4265) 2022-08-27 19:20:29 -03:00
Alejandro Martinez
efd9253352 Update translations to include latest strings before release
To enable testing and finish translations
[publish binaries]
2022-08-27 10:38:42 -03:00
Alejandro Martinez
aae3376135 R athlete.zones - generalize for all sports and add hr/pace lows
Fixes #4262
2022-08-25 22:59:45 -03:00
Alejandro Martinez
c1bbe1b590 Python athleteZones - generalize for all sports and add hr/pace lows
Part 1 of #4262
2022-08-25 20:03:36 -03:00
Alejandro Martinez
f8b6cc6c17 FixElevation - Use post instead of get for open-elevation requests
This allows to request all points at once since post api has
no limits according the documentation.
Break logic is preserve just in case we need it in the future.
Fixes #4261
2022-08-25 12:21:46 -03:00
Alejandro Martinez
82df874e54 Update German translation
Contributed by Marcen at the users forum
2022-08-24 19:00:53 -03:00
Alejandro Martinez
7b44eaa7a8 Deprecate Google Drive and Calendar due to changes in OAuth
Fixes #4259
2022-08-24 18:55:44 -03:00
Alejandro Martinez
a31ce926dc Enable Estimator debug as a runtime option
It can be enables adding:
--debug-rules "gc.estimator.debug=true"
to the command line.
2022-08-24 13:04:03 -03:00
Alejandro Martinez
481e11fffc Avoid random crash in HrPwPlot when HR>=220
Fixes #4260
2022-08-24 12:37:14 -03:00
Alejandro Martinez
0108a05f5a Fit file import - Interpolate lrbalance between valid values only
Fixes #4117
2022-08-23 18:03:59 -03:00
Alejandro Martinez
700f855ce1 Strava download - Update RPE field if present
Fixes #3444
NB: activity creation doesn't support this paramter,
so it is only one way sync for the moment.
2022-08-23 12:37:03 -03:00
Alejandro Martinez
1e8220237c Update Python library with missing constants for Qt Charts
Documented in the wiki. Fixes #4009
TODO: annotate is disabled and it needs work to support the different
types.
2022-08-23 11:27:42 -03:00
Alejandro Martinez
6914832c24 Snapshot builds to test Fix Elevation using Open-Elevation.com
MapQuest API reaches EOL on Aug-31, let's test the replacement
in all the supported platforms.
Reveal Controls are disabled in this build for all charts,
with Show Console on chart settings for R and Python charts.
[publish binaries]
2022-08-22 18:49:53 -03:00
Alejandro Martinez
07f672ff80 Add GC_ALIGN_NONE to Python Library
[skip ci]
2022-08-22 10:05:38 -03:00
Alejandro Martinez
d58c539c00 User Chart Axis Settings - Show/Hide log option
According to Axis type, currently it is supported
for continuous axis only.
2022-08-21 19:05:55 -03:00
Alejandro Martinez
a0a2b28629 Update user chart dialogs for the wiki
[skip ci]
Fixes #4115
2022-08-21 19:04:56 -03:00
Alejandro Martinez
3a34f7ce55 FixElevation - Change MapQuest to Open-Elevation (#4258)
Since MapQuest elevation service reaches end of life on aug-31,
it is replaced by Open-Elevation public API with minimum changes.
TODO: use Post instead of Get to request more points at a time
Fixes #4206
2022-08-20 12:17:56 -03:00
Mark Liversedge
84eceebd00 Fix metric refresh SEGV
.. when athlete has < 10 activies modulo 0 causes arithmetic
   operation crash (divide by zero).
2022-08-17 23:20:42 +01:00
Mark Liversedge
853e248383 FIT nongarmin.json remove duplicate entries
.. added same rows twice in error.

[skip ci]
2022-08-17 14:28:32 +01:00
Mark Liversedge
ce089de33e FITmetadata.json
.. clarify how to make updates in the README

.. replace the fit_example.h from the current SDK

.. added Garmin devices not yet supported in the SDK to
   the nongarmin.json file

.. updated the makefile to use python3 and update when
   the python program is changed.
2022-08-17 14:20:16 +01:00
Alejandro Martinez
3180a166d8 Disable Reveal Controls
For R and Python charts the Show Console setting is now
part of regular settings, and it is replaced by a warning
label when R or Python are disabled to help users.
Since for remaining charts reveal controls are redundant,
they are globally disabled in Perspective class.
TODO: remove all reveal code to simplify charts,
eventually after v3.6 release to minimize risks?
Fixes #4256
2022-08-14 21:12:10 -03:00
Alejandro Martinez
f3b78338ac Update German translation
Contributed by Marcen at the forum
2022-08-14 17:42:10 -03:00
Alejandro Martinez
02cab3029b Travis-ci - cache macOS app package
[skip AppVeyor]
To avoid rebuild when after_success is cancelled,
so restarting the job can complete the packaging.
Drawback is we need to clear the cache to rebuild
[publish binaries]
2022-08-13 16:41:37 -03:00
Mark Liversedge
47355d17fe V3.6-RC2 Build Trigger
[publish binaries]
2022-08-13 11:22:12 +01:00
Andreas Buhr
716f40ab3a Some fixes around margins for Qt6 2021-07-30 13:38:31 +02:00
Andreas Buhr
7be3df19eb move from screen()[0] to primaryScreen() 2021-07-26 13:17:11 +02:00
Andreas Buhr
85ab8211b0 Qt6: remove QDesktopWidget usage 2021-07-26 13:11:44 +02:00
Andreas Buhr
7abac2678b Usage of QDesktopWidget is deprecated. Adapt code
This patch adapts the code to not use QDesktopWidget but to
use QGuiApplication::screens instead. It defaults to screen number 0.
2021-07-26 13:11:30 +02:00
Andreas Buhr
4aeade9cf5 Add assignment operators to some classes
The implicitly defined assignment operator for classes having custom
defined copy constructor is deprecated. This patch adds explicit
assignment operators.
2021-07-20 21:49:13 +02:00
1573 changed files with 153738 additions and 170085 deletions

2
.gitignore vendored
View File

@@ -14,6 +14,8 @@ Makefile
*.swp
*.user
*.AppImage
*.tab.c
*.tab.h
# osx noise
.DS_Store

View File

@@ -14,6 +14,7 @@ cache:
- D2XX
- site-packages
- VLC
- src/GoldenCheetah.app
env:
global:
@@ -40,14 +41,19 @@ env:
- secure: gUDTEErUOhzkSVofEvdw1jqHHsE/K+/SOqRBKDToaFPhi6XK+Tvu1LqPMjfPdjYLaCSiwc/R79fJrAEuK+7KSwdiLEnDv3RMpRS5g1UWyJ/ZYd5xNR+WiBqUvnY/S/CJokuNw7gBbGq7JCO4pmIGV5YB9FA4Na6MG/eHzTSOIig=
- secure: Qk+gzBLwjrB8abUYzxap10dYSpIeKpB1gqhdoMbqS23G0r1lejnsjutIfReuJGK/efCmhisKN1xIX/InvJWD8z6GsLJFmf3F0oRj7aDJ/X5UIn9Upflje9xgHQafP1FJuzZBWtzandNfPE8EmEOgAQsJZ3c7xBE1SY/6xcJaQTc=
- secure: m4+k3/QcYvqmMoRO8uq3ef2jAO1FWeRVDG/XtlbjBlgmB5OR/zW5c7c1Ywm6IM5yzsi1rRks8GFffZ6gYqXhML10EfGKVbnyBcZZ7HVylNtvxDF68W1BLacChzDs4mGYQSV8kJRGI3EaVNdyFJ5yln/HUZ6qBbQ473MtxprO6BI=
- secure: GEyUuLuIc7D3F4noKhtTCbWbQAlm61Y7Vh2mOKBEgmyfoV1johwlEL0RaeRyr9MnU2MN+4jeFthvDjxm3LGP19zrpB46GTGHU6/H9BZBodDCJsFTqj32T+5QTcAF2RQ66ZgYpSyTf063/RLlfy7YjCb8KLiJ2asCaoYtQIjx3hA=
- secure: LvO6/hNrhZo/4GCy4QoXV4V1UucnSt1upKg5K5LF0KgVOrAENYny0zdOJZgT5f6rTWLTU4WlY9ZXzipEhsyBMeWF8SH2LmDYvqHj5gTb3ANNgvvgVyutwq2XqnMTTrJy38CJaoLHHAF4uxkKr22omjSNzHKntAis95VjnIXLxug=
- secure: iMqhxWG5UXT/mPGiisqMlFTH9fr06H511FfhcBsKjXS5GT0xxqTscDkN7t6umljyMefFbf32lVaryzIlE/nd9858DYK8yxm4pj8Q9CFVpKFIH5NTC6l4vH1PT3FfeMpkoA0/n1G3bZbiVwi4smHDyxNXRyIaAWUAlCVmg2B1IFM=
jobs:
include:
- os: osx
osx_image: xcode11.3
- if: commit_message !~ /\[skip osx\]/
os: osx
osx_image: xcode14.2
compiler: clang
- os: linux
dist: bionic
- if: commit_message !~ /\[skip linux\]/
os: linux
dist: focal
compiler: gcc
before_install:

View File

@@ -6,7 +6,7 @@
#### **Do you have questions about the source code?**
* Ask any question about how to build GoldenCheetah or anything related to the source code in the [golden-cheetah-developers mailing list](https://groups.google.com/forum/#!forum/golden-cheetah-developers), please see the [GoldenCheetah Developers Guide](https://github.com/GoldenCheetah/GoldenCheetah/wiki/Developers-guide) for addtional information.
* Ask any question about how to build GoldenCheetah or anything related to the source code in the [golden-cheetah-developers mailing list](https://groups.google.com/forum/#!forum/golden-cheetah-developers), please see the [GoldenCheetah Developers Guide](https://github.com/GoldenCheetah/GoldenCheetah/wiki/Developers-guide) for additional information.
## How to contribute to GoldenCheetah

View File

@@ -27,7 +27,6 @@ CONTENTS
- FTDI D2XX
- SRMIO
- liboauth
- libkml
- libvlc - Video playback in training mode
- libical - Diary window and CalDAV support (external calendar integration)
- libusb - If you want support for using USB2 sticks in Train View
@@ -93,16 +92,14 @@ Uncomment below and configure the location of the GNU scientific library, this i
#GSL_INCLUDES = /usr/include
#GSL_LIBS = -lgsl -lgslcblas -lm
Ensure you have the following lines (which are now also in gcconfig.pri.in which has
been updated to reflect the new dependencies in version 3.6)
Uncomment the following lines to use flex and bison:
QMAKE_LEX = flex
QMAKE_YACC = bison
win32 {
QMAKE_YACC = bison --file-prefix=y -t
QMAKE_MOVE = cmd /c move
QMAKE_DEL_FILE = rm -f
}
#QMAKE_LEX = flex
#QMAKE_YACC = bison
and if you are using bison 3.7 or higher, make sure to also uncomment:
#QMAKE_MOVE = cp
To compile translation you need the QT tool lrelease
If it is not found using the defaults in src/src.pro then set the full path and
@@ -114,7 +111,7 @@ and add the library path to LIBZ_INCLUDE =, you will need to have the compress l
#LIBZ_INCLUDE =
#LIBZ_LIBS = -lz
compiling with gcc -O3 (tree vectorization can have a significat impact)
compiling with gcc -O3 (tree vectorization can have a significant impact)
[or -Ofast]
If so you might like to uncomment:
@@ -207,51 +204,6 @@ $ make
You now have SRM support built in.
LIBKML - For export to Google Earth
-----------------------------------
You will need Google Earth 5.2 or later and therefore libkml that supports this.
$ sudo apt-get install libkml-dev
if this does not work you will need to build from source:
$ sudo apt-get install subversion
$ sudo apt-get install expat libexpat1 libexpat1-dev
Once svn is installed you can grab the libkml source, configure, build and
install:
$ cd ~/Projects
$ svn checkout http://libkml.googlecode.com/svn/trunk/ libkml
$ cd libkml
You will need automake and friends (see SRMIO above)
$ sh autogen.sh
$ ./configure
$ make
$ make install
$ sudo make install
If you get errors about use of 'long long' then edit:
- src/kml/{convenience,dom,engine,regionator,xsd}/Makefile
- examples/{engine,gpx,gx,hellonet,helloworld,regionator,xsd}/Makefile
- and look for the flag -pedantic and remove it. I got this on Linux 64bit builds ymmv.
Once libkml is installed:
$ cd ~/Projects/GoldenCheetah/src
$ vi gcconfig.pri
Ensure KML_INSTALL=/usr/local
Make clean is needed if you have previously built, since source files examine
#defines before including this feature. You can skip it if you know why ;)
$ make clean
$ qmake
$ make
You can now export rides to Google Earth kml format.
LIBICAL - Diary integration with Google or MobileMe calendars
-------------------------------------------------------------

View File

@@ -1,35 +1,29 @@
Update Note: to build GoldenCheetah v3.6 we are using the Homebrew Package
Manager to install dependencies, including Qt and GSL, on Travis-ci
macOS Mojave build environment.
You can check the travis/osx folder for the complete and updated build scripts,
the minimum Qt version known to work is 5.13 with Qt WebEngine and Qt Charts.
GSL - GNU Scientific Library is a mandatory dependency starting with v3.6
Ale Martinez - Jul, 2022
+++++++++++++++++++++++
MAC OSX BUILD WALKTHROUGH
MACOS BUILD WALKTHROUGH
+++++++++++++++++++++++
Mark Liversedge
Ale Martinez
Jan 2015
Version 1.2
Mar 2024
Version 3.7
A walkthrough of building GoldenCheetah from scratch on Mac OSX. This was performed
on Mac OSX Lion (10.7) but the instructions are largely the same for all versions of
Mac OS X.
on macOS Sonoma (14.4) but the instructions are largely the same for all current
versions of macOS.
CONTENTS
1. BASIC INSTALLATION WITH MANDATORY DEPENDENCIES
- Xcode
- HomeBrew
- Qt
- GSL
- Bison
2. ADDING OPTIONAL DEPENDENCIES
- FTDI D2XX
- SRMIO
- libkml
- libusb
- libical
@@ -40,28 +34,24 @@ CONTENTS
Depending upon the speed of your internet connection and availability of the
required software the steps in section 1 will take approximately 1 hour.
1.1 Ensure OS X is up-to-date
-----------------------------
1.1 Ensure macOS is up-to-date
------------------------------
Make sure you have applied all the latest updates to Mac OS X. This can be
found from the system menu, apple, about this mac, software update.
This walkthrough was performed on an iMac running 10.7.2 (Lion)
This walkthrough was performed on a MacBook Air running 14.4 (Sonoma)
1.2 Install XCode from App Store
--------------------------------
If you are building on 10.6 or higher you should install Xcode4, for earlier
releases you will need Xcode 3.1.4. If you have capable hardware you should
consider upgrading to Lion to get the latest bug fixes and capabilities.
To install Xcode on Lion you need to download it via the App Store. You can
To install Xcode on macOS you need to download it via the App Store. You can
launch the App Store from launchpad, or it may be already in your dock.
Under the search box type in Xcode and it will return a few optios, generally
Under the search box type in Xcode and it will return a few options, generally
Xcode is the first item and shows a blueprint with a hammer icon. Click on
this to install it. It should be free. The usual app store process will apply
as the application is downloaded and installed. The download is about 2GB
as the application is downloaded and installed. The download is about 4GB
so do bear this in mind if you have limits on your internet bandwidth or cap.
1.3 Run the Xcode installer
@@ -75,11 +65,7 @@ SDKs. It also installs the 'git' tool for working with Git repositories.
It will run through a wizard to install, just read and then accept the license
agreement and let it get on with it. If you don't like the license then quit
and use the development builds from goldencheetah.stand2surtf.net.
You may find it borks at iTunes helper running, you will
need to force quit the iTunes helper via Finder, Applications, Utilities,
Activity Monitor if this happens.
and use the developemnt or snapshot builds from https://www.goldencheetah.org
1.4 Get the source code
-----------------------
@@ -92,7 +78,7 @@ First open up a terminal session, then;
$ cd
$ mkdir Projects
$ cd Projects
$ git clone git://github.com/GoldenCheetah/GoldenCheetah.git
$ git clone https://github.com/GoldenCheetah/GoldenCheetah.git
You will now have the GoldenCheetah sources downloaded into a 'GoldenCheetah'
directory in your home directory, under another folder called 'Projects'.
@@ -106,65 +92,44 @@ build a release you need to checkout the code at the tag for the release.
A list of releases can be found at: https://github.com/GoldenCheetah/GoldenCheetah/tags
$ git checkout V3.3-RC1
$ git checkout V3.6
$ ls
You will now see an updated version of this walkthrough, please jump to using
that since it may be more up-to-date than this walkthrough (depending upon
where you got it from of course!).
The following walkthrough is based on latest master, if you want to build v3.6 please
see the travis scripts in the repository.
1.5 Install the QT SDK
----------------------
1.5 Install HomeBrew
--------------------
GoldenCheetah is developed using the Nokia QT toolkit, it is large and will
need to be downloaded and installed from their website. Alternatively, you
can intall qt via macports (http://www.macports.org) as described in section
1.5.1.
The easiest way to install GoldenCheetah dependencies on macOS is via HomeBrew package
manager, if you don't have it installed yet, follow the instructions in their home page:
https://brew.sh/
As of today, the latest stable release is 5.6.0, we need 4.7 or higher so
go ahead and download the offline installer - it has everything you need
but is about 1.3GB. Please make sure you download the installer for Mac
OS X 10.6 or later, 64-bit.
The url for QT downloads is: https://www.qt.io/download-open-source/#section-2 and
whilst the offline installer is only 12mb it will still call back and download the
required objects as you install, I think it is better to get it all in
one hit (and you can save it to reinstall on another computer or if you
want to rebuild/reinstall for any other reason).
Once the QT SDK is downloaded you will have a .dmg (disk image) that you
need to mount by double clicking on it. You will then get a volume mounted
and shown on your desktop. Go ahead and double click that to start the install
process. It is probably called something like 'Qt SDK Installer'.
It will popup with a dialog warning that this is downloaded from the internet
and are you sure you want to open it? Go ahead and click Open.
A wizard will now guide you through the QT install process. Go ahead and accept
all the defaults, it will install in your home directory and avoid updating the
system directories, this means you are less likely to bork your Mac OSX installation.
Read and accept the license agreement and then continue and install.
We need to make sure that a program called qmake is installed in a directory where
it can be found. So, we need to create a link from what we just installed in the
user programs folder. For QT SDK (5.6) we need to:
$ sudo ln -s ~/Qt5.6.0/5.6/clang_64/bin/qmake /usr/local/bin/qmake
1.5.1 Install via Mac Ports
---------------------------
If you have macports installed, you can install the qt dependices
with the following commands:
$ sudo port install qt4-mac
$ sudo port install qt4-mac-sqlite3-plugin
1.6 DEPRECATED
1.6 Install Qt
--------------
No longer need this step (install boost)
Latest stable release can be installed as:
$ brew update
$ brew install Qt6
Follow the instructions to add Qt to PATH and test using:
$ qmake --version
1.6 Install GSL and Bison
-------------------------
GSL is a mandatory dependency from v3.6, you can install using HomeBrew:
$ brew install gsl
The Bison version included in Xcode is too old (2.3), you can install a
newer version using HomeBrew:
$ brew install bison
adding it to PATH as indicated, check version using:
$ bison --version
1.7 Configure and Build GoldenCheetah (with no optional dependencies)
---------------------------------------------------------------------
@@ -181,37 +146,23 @@ $ vi gcconfig.pri
In that last step you can use whatever editor you feel most comfortable with.
For now we will comment out some of the dependencies we have not installed
support for yet:
#SRMIO_INSTALL = /usr/local/srmio
#D2XX_INCLUDE = /usr/local/include/D2XX
we may need to additionally configure to use the local compression
libraries (at least I did), by adding the following line:
LIBS += -lz
Lastly, since we are on Lion, we can also uncomment and change the following line:
and GSL location:
DEFINES += GC_HAVE_LION
GSL_INCLUDES = /usr/include
GSL_LIBS = -L/opt/homebrew/lib/ -lgsl -lgslcblas -lm
Once the changes have been made we are now ready to build for the first time. You
may notice a lot of warning messages about the version of O/S not being supported.
This is because QT does not officially support Lion at this point in time (but it
does work). You can either ignore the warning messages or (like me) go and edit out
the warning (once you have seen the message once you don't need reminding every
time you compile).
Lastly, we can also uncomment and change the following line:
To do this, edit the file in question as an administrator:
QMAKE_MOVE = cp
$ sudo vi ~/QtSDK/Desktop/Qt/474/gcc/include/QtCore/qglobal.h
if Bison version is higher than 3.7
And comment out line 320 (or thereabouts):
//# warning "This version of Mac OS X is unsupported"
Once this is done you can kick off the build:
Once the changes have been made we are now ready to build for the first time.
$ cd .. #this should put you in the top level dir containing this file
$ qmake -recursive
@@ -222,12 +173,6 @@ When build first time you get number of error messages on .qm files missing:
You can ignore these messages for your build. The .qm files will be created during the
build at a later point in time via the "lrelease" command you configured in gcconfig.pri)
If make fails to find a Makefile then qmake is configured, by default, to create
an xcode project file. You will need to change the qmake command above to tell it
to create a makefile with the following:
$ qmake -spec macx-g++ -recursive
$ make
Once this completes you will have a GoldenCheetah.app in the src directory which
can be launched:
@@ -249,55 +194,19 @@ $ open src/GoldenCheetah.app
2. ADDING OPTIONAL DEPENDENCIES
===============================
- D2XX
- SRMIO
- libkml
- libusb
- libical
- Python embedding
- R embedding
Since these optional dependencies are more complex and require more advanced
technical skills we do not provide a walkthrough for building them all but
instead provide the configure settings and any special considerations that
should be taken into account.
2.1 SRMIO - For working with PC 5/6/7
-------------------------------------
SRMIO (git)
./configure CFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64" CPPFLAGS=-I/usr/local/D2XX/ --disable-dependency-tracking
2.2 libkml - For export to Google Earth
---------------------------------------
expat (2.0.1)
./configure CFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64" --disable-dependency-tracking
libkml (pulled down from the svn repo)
./configure CFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64" --disable-dependency-tracking --with-expat-include-dir=/usr/local/include --with-expat-lib-dir=/usr/local/lib --disable-swig CXXFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64"
note: the added CXXFLAGS helped clear the -Werror flag that stopped compilation.
2.3 libusb - For Garmin USB2 stick support
------------------------------------------
libusb (0.1.12)
To compile on OSX you need to apply the patch here:
https://trac.macports.org/browser/trunk/dports/devel/libusb-legacy/files?rev=97840
Then:
./configure --prefix=/opt/libusb/ CFLAGS="-arch x86_64" CXXFLAGS="-arch x86_64" --disable-dependency-tracking
then
sed -i 'bak' 's|CC -dynamiclib|CC -dynamiclib -arch x86_64|g' libtool
make
make install
note: that the sed line updates some commands in libtool. not sure why the arch clags are not getting passed.
2.4 libical
-----------
libical (0.46)
first run autogen.sh
then
./configure CFLAGS="-isysroot /Developer/SDKs/MacOSX10.7.sdk -arch x86_64" --disable-dependency-tracking
See Travis scripts in the repository for the changes you need to make:
- travis/osx/before_install.sh
- travis/osx/before_script.sh
and then rebuild.

View File

@@ -1,6 +1,6 @@
Update Note: to build GoldenCheetah v3.6 we are using Microsoft Visual C++ 2019,
included in Microsoft Visual Studio 2019 AppVeyor image, with Qt5.15.2 and GSL 2.7
insalled with vcpkg, on AppVeyor continuous integration platform.
installed with vcpkg, on AppVeyor continuous integration platform.
You can check the appveyor.yml for the complete and updated build script,
the minimum Qt version known to work is 5.13 with Qt WebEngine and Qt Charts.
GSL - GNU Scientific Library is a mandatory dependency starting with v3.6
@@ -50,7 +50,7 @@ You need:
- Flex and Bison (below the version working for me)
-- Download from here: https://sourceforge.net/projects/winflexbison/
-- Use the "win_flex_bison-latest.zip" version
-- Unzip whereever you like and make sure that the location "win_bison.exe" and "win_flex.exe
-- Unzip wherever you like and make sure that the location "win_bison.exe" and "win_flex.exe
are added to your "Path" environment variable
- Qt C++ Framework
@@ -165,10 +165,6 @@ Info: I plan to provide a pre-compiled set of the dependencies for the Windows v
The version currently used is: "CDM v2.10.00 WHQL Certified" - while there are more recent
version available for download.
- Google Earth .kml files (export)
-- Is part of the official build as a static lib - build is done with MSVC2015 - the build uses Release 1.2
(path of source code has changed to https://github.com/google/libkml)
- iCal Calendar support (prerequisite for the "Diary" view)
-- Is part of the official build as a static lib - the build uses Release 1.0.1
@@ -190,7 +186,7 @@ Building with integration to external services (via APIs)
As of today a number of integrations with external services like Strava, Cyclinganalytics,
Google Calendar, Dropbox, Today's Plan, Google Drive, CloudDB) exist in the official GoldenCheetah
builds. The permission to use API's of such services requires a dedicated registration (in this case
for "GoldenCheetah" as the consumer of the services) where in return the GoldenCheetah team get's
for "GoldenCheetah" as the consumer of the services) where in return the GoldenCheetah team gets
specific credentials to access the services.
All of the services request that the access credentials are kept private and are under responsibility

View File

@@ -1,12 +1,29 @@
<img src="src/Resources/images/gc.png" height="25%" width="25%">
# GoldenCheetah
<img src="https://raw.githubusercontent.com/GoldenCheetah/GoldenCheetah/067696aafdad21c702672b2c9c41da03c076451c/doc/wiki/GoldenCheetah-Screenshot.png" width="100%">
## About
GoldenCheetah is a desktop application for cyclists and triathletes and coaches, providing a rich set of tools and models to analyse, track and predict performance, optimise aerodynamics and train indoors.
GoldenCheetah is a desktop application for cyclists and triathletes and coaches
* Analyse using summary metrics like BikeStress, TRIMP or RPE
* Extract insight via models like Critical Power and W'bal
* Track and predict performance using models like Banister and PMC
* Optimise aerodynamics using Virtual Elevation
* Train indoors with ANT and BTLE trainers
* Upload and Download with many cloud services including Strava, Withings and Todays Plan
* Import and export data to and from a wide range of bike computers and file formats
* Track body measures, equipment use and setup your own metadata to track
GoldenCheetah integrates with most popular cloud services like Strava and Todays Plan, imports data from bike computers, imports downloads from any website like TrainingPeaks and Garmin and will also connect to smart trainers using ANT+ and Bluetooth.
GoldenCheetah provides tools for users to develop their own own metrics, models and charts
* A high-performance and powerful built-in scripting language
* Local Python runtime or embedding a user installed runtime
* Embedded user installed R runtime
GoldenCheetah supports community sharing via the Cloud
* Upload and download user developed metrics
* Upload and download user, Python or R charts
* Import indoor workouts from the ErgDB
* Share anonymised data with researchers via the OpenData initiative
GoldenCheetah is free for everyone to use and modify, released under the GPL v2 open source license with pre-built binaries for Mac, Windows and Linux.
@@ -19,8 +36,7 @@ INSTALL-WIN32 For building on Microsoft Windows
INSTALL-LINUX For building on Linux
INSTALL-MAC For building on Apple OS X
INSTALL-MAC For building on Apple MacOS
macOS and Linux: [![Build Status](https://app.travis-ci.com/GoldenCheetah/GoldenCheetah.svg?branch=master)](https://app.travis-ci.com/GoldenCheetah/GoldenCheetah)

View File

@@ -1,6 +1,7 @@
version: ci.{build}
image: Visual Studio 2019
clone_depth: 1
skip_tags: true
environment:
GC_GOOGLE_CALENDAR_CLIENT_SECRET:
@@ -21,8 +22,6 @@ environment:
secure: 7pCVnVEKKmSU4SZN6IFqUw==
GC_STRAVA_CLIENT_SECRET:
secure: n3cMS1yy709xhSnTeWABMsoAIkJzy5euh3Pw4ehv0BzszJKoWkypF0cyW8RXSm3M
GC_TODAYSPLAN_CLIENT_SECRET:
secure: 7PnFB8cfahFT6LyP64eB7N1vkbwVaULpB2ORmEkn+J75zNB1xxGClFNXSHZ7kXhB
GC_CYCLINGANALYTICS_CLIENT_SECRET:
secure: UY+m3YypNNLUzKyGdrLw8xdCvxuQWRZi9EHS3j1ubLC4qyRL7iEVW6ubumfdh6gT
GC_CLOUD_DB_BASIC_AUTH:
@@ -41,6 +40,10 @@ environment:
secure: mmMksvVnfBiXufBDn2gAhQY53n0J9BokSCtDY51uU918QJ/LL4XOojtJp5tMFn8T7ugyDhNASpqZXiK55vxSD53vm+tjufpfzppKEeh93Babvc/VrndLB1X/RZCRUQTR6rka05fYl4e0eBzP1H091A==
GC_XERT_CLIENT_SECRET:
secure: /1rVLT8LyJCZ4xNJ5W+NtAcZ1rtKaUjW9SYm/T3gHoc=
GC_AZUM_CLIENT_SECRET:
secure: 2ZpXsA3TQv1zftYVyZSF6f83ftCzza+K22ZX1doj7Yc/5dmGl1bnsSeVChJgJ8lQ2fRPYpdmun9cjqwcrtG/zXTTsYuTvYWegHz/4Y0u6Mg=
GC_TRAINERDAY_API_KEY:
secure: nDgxUdgLkp0+gaxKRCaAVD5WYAl9pLmOnZ9JLSx3ulqT346nieakd02V3Q7dZYEU
init:
# Setup QT 5.15 - 64Bit
@@ -61,7 +64,7 @@ cache:
- C:\R
- C:\Python -> src\Python\requirements.txt
- c:\tools\vcpkg\installed\
- qwt
- qwt -> qwt/qwtconfig.pri.in
install:
# Get the libraries
@@ -113,7 +116,7 @@ install:
- nmake install
- cd ..
# Add Python (avoiding colision between GC Context.h and Python context.h)
# Add Python (avoiding collision between GC Context.h and Python context.h)
- echo DEFINES+=GC_WANT_PYTHON >> src\gcconfig.pri
- echo PYTHONINCLUDES=-ICore -I\"c:\python37-x64\include\" >> src\gcconfig.pri
- echo PYTHONLIBS=-L\"c:\python37-x64\libs\" -lpython37 >> src\gcconfig.pri
@@ -132,6 +135,10 @@ before_build:
# Add Train Robot
- echo DEFINES+=GC_WANT_ROBOT >> src\gcconfig.pri
# Enable TrainerDay Query API; pagesize depends on the keys remote configuration
- echo DEFINES+=GC_WANT_TRAINERDAY_API >> src\gcconfig.pri
- echo DEFINES+=GC_TRAINERDAY_API_PAGESIZE=25 >> src\gcconfig.pri
# Avoid macro redefinition warnings
- echo DEFINES+=_MATH_DEFINES_DEFINED >> src\gcconfig.pri
@@ -149,7 +156,6 @@ before_build:
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_NOKIA_CLIENT_SECRET__', $env:GC_NOKIA_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_DROPBOX_CLIENT_SECRET__', $env:GC_DROPBOX_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_STRAVA_CLIENT_SECRET__', $env:GC_STRAVA_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_TODAYSPLAN_CLIENT_SECRET__', $env:GC_TODAYSPLAN_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_CYCLINGANALYTICS_CLIENT_SECRET__', $env:GC_CYCLINGANALYTICS_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_CLOUD_DB_BASIC_AUTH__', $env:GC_CLOUD_DB_BASIC_AUTH | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_CLOUD_DB_APP_NAME__', $env:GC_CLOUD_DB_APP_NAME | Set-Content src\Core\Secrets.h
@@ -159,6 +165,8 @@ before_build:
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_NOLIO_CLIENT_ID__', $env:GC_NOLIO_CLIENT_ID | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_NOLIO_SECRET__', $env:GC_NOLIO_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_XERT_CLIENT_SECRET__', $env:GC_XERT_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_AZUM_CLIENT_SECRET__', $env:GC_AZUM_CLIENT_SECRET | Set-Content src\Core\Secrets.h
- ps: (Get-Content src\Core\Secrets.h) -replace '__GC_TRAINERDAY_API_KEY__', $env:GC_TRAINERDAY_API_KEY | Set-Content src\Core\Secrets.h
build_script:
- qmake.exe build.pro -r -spec win32-msvc
@@ -190,11 +198,11 @@ after_build:
- copy ..\Resources\win32\gc.ico
# Installer script
- copy ..\Resources\win32\GC3.6-Dev-Master-W64-QT5.nsi
- copy ..\Resources\win32\GC3.7-Master-W64-QT5.nsi
# Build the installer
- makensis GC3.6-Dev-Master-W64-QT5.nsi
- move GoldenCheetah_v3.6-DEV_64bit_Windows.exe ..\..\GoldenCheetah_v3.6-DEV_x64.exe
- makensis GC3.7-Master-W64-QT5.nsi
- move GoldenCheetah_v3.7-DEV_64bit_Windows.exe ..\..\GoldenCheetah_v3.7-DEV_x64.exe
- cd ..\..
- ps: Set-AppveyorBuildVariable -Name 'PUBLISH_BINARIES' -Value false
- ps: if ($env:APPVEYOR_REPO_COMMIT_MESSAGE_EXTENDED -Match "\[publish binaries\]") { Set-AppveyorBuildVariable -Name 'PUBLISH_BINARIES' -Value true }
@@ -203,28 +211,26 @@ test_script:
# minimum test
- src\release\GoldenCheetah --version 2>GCversionWindows.txt
- git log -1 >> GCversionWindows.txt
- ps: CertUtil -hashfile GoldenCheetah_v3.6-DEV_x64.exe sha256 | Select-Object -First 2 | Add-Content GCversionWindows.txt
- ps: CertUtil -hashfile GoldenCheetah_v3.7-DEV_x64.exe sha256 | Select-Object -First 2 | Add-Content GCversionWindows.txt
- type GCversionWindows.txt
artifacts:
- path: GoldenCheetah_v3.6-DEV_x64.exe
- path: GoldenCheetah_v3.7-DEV_x64.exe
name: GCinstaller
- path: GCversionWindows.txt
name: GCversionWindows
deploy:
# deploy continuous builds to s3
- provider: S3
access_key_id:
secure: RoEkfKfOnF7JHOiLZX5qfZM08X+bu4oaDzzSKgdooNM=
secret_access_key:
secure: GPAArawatirYwgpHJBthdrbvyFU5bBzPOdK7VYYPiG2YHYi/DNJZ5Q5qGK1A440p
bucket: goldencheetah-binaries
region: us-east-1
remove_files: true
set_public: true
folder: Windows
# deploy continuous builds to GitHub release
- provider: GitHub
auth_token:
secure: 807DE/9vib/Kjz5Tah/Zc6zkoigLEWRzASw/DUWjLwZ5d8HHomXqWQ7iln4VtOqL
release: snapshot
description: 'Snapshot Builds'
artifact: GCinstaller, GCversionWindows
draft: false
prerelease: true
force_update: true
on:
PUBLISH_BINARIES: true
APPVEYOR_REPO_NAME: "GoldenCheetah/GoldenCheetah"

View File

@@ -123,7 +123,7 @@ void HttpConnectionHandlerPool::loadSslConfig() {
sslConfiguration->setLocalCertificate(certificate);
sslConfiguration->setPrivateKey(sslKey);
sslConfiguration->setPeerVerifyMode(QSslSocket::VerifyNone);
sslConfiguration->setProtocol(QSsl::TlsV1SslV3);
sslConfiguration->setProtocol(QSsl::TlsV1_0);
wDebug("HttpConnectionHandlerPool: SSL settings loaded");
#endif

View File

@@ -1,75 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Solution of linear systems involved in the Levenberg - Marquardt
// minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/********************************************************************************
* LAPACK-based implementations for various linear system solvers. The same core
* code is used with appropriate #defines to derive single and double precision
* solver versions, see also Axb_core.c
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "levmar.h"
#include "misc.h"
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_CNST(x) (x)
#ifndef HAVE_LAPACK
#include <float.h>
#define LM_REAL_EPSILON DBL_EPSILON
#endif
#include "Axb_core.c"
#undef LM_REAL
#undef LM_PREFIX
#undef LM_CNST
#undef LM_REAL_EPSILON
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#ifndef HAVE_LAPACK
#define LM_REAL_EPSILON FLT_EPSILON
#endif
#include "Axb_core.c"
#undef LM_REAL
#undef LM_PREFIX
#undef __SUBCNST
#undef LM_CNST
#undef LM_REAL_EPSILON
#endif /* LM_SNGL_PREC */

File diff suppressed because it is too large Load Diff

View File

@@ -1,49 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef _COMPILER_H_
#define _COMPILER_H_
/* note: intel's icc defines both __ICC & __INTEL_COMPILER.
* Also, some compilers other than gcc define __GNUC__,
* therefore gcc should be checked last
*/
#ifdef _MSC_VER
#define inline __inline // MSVC
#elif !defined(__ICC) && !defined(__INTEL_COMPILER) && !defined(__GNUC__)
#define inline // other than MSVC, ICC, GCC: define empty
#endif
#ifdef _MSC_VER
#define LM_FINITE _finite // MSVC
#elif defined(__ICC) || defined(__INTEL_COMPILER) || defined(__GNUC__)
#define LM_FINITE finite // ICC, GCC
#else
#define LM_FINITE finite // other than MSVC, ICC, GCC, let's hope this will work
#endif
#ifdef _MSC_VER
#define LM_ISINF(x) (!_finite(x) && !_isnan(x)) // MSVC
#elif defined(__ICC) || defined(__INTEL_COMPILER) || defined(__GNUC__)
#define LM_ISINF(x) isinf(x) // ICC, GCC
#else
#define LM_ISINF(x) isinf(x) // other than MSVC, ICC, GCC, let's hope this will work
#endif
#endif /* _COMPILER_H_ */

View File

@@ -1,398 +0,0 @@
/*
////////////////////////////////////////////////////////////////////////////////////
//
// Prototypes and definitions for the Levenberg - Marquardt minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
////////////////////////////////////////////////////////////////////////////////////
*/
#ifndef _LEVMAR_H_
#define _LEVMAR_H_
/************************************* Start of configuration options *************************************/
/* Note that when compiling with CMake, this configuration section is automatically generated
* based on the user's input, see levmar.h.in
*/
/* specifies whether to use LAPACK or not. Using LAPACK is strongly recommended */
//#define HAVE_LAPACK
/* specifies whether the PLASMA parallel library for multicore CPUs is available */
/* #undef HAVE_PLASMA */
/* to avoid the overhead of repeated mallocs(), routines in Axb.c can be instructed to
* retain working memory between calls. Such a choice, however, renders these routines
* non-reentrant and is not safe in a shared memory multiprocessing environment.
* Bellow, an attempt is made to issue a warning if this option is turned on and OpenMP
* is being used (note that this will work only if omp.h is included before levmar.h)
*/
#define LINSOLVERS_RETAIN_MEMORY
#if (defined(_OPENMP))
# ifdef LINSOLVERS_RETAIN_MEMORY
# ifdef _MSC_VER
# pragma message("LINSOLVERS_RETAIN_MEMORY is not safe in a multithreaded environment and should be turned off!")
# else
# warning LINSOLVERS_RETAIN_MEMORY is not safe in a multithreaded environment and should be turned off!
# endif /* _MSC_VER */
# endif /* LINSOLVERS_RETAIN_MEMORY */
#endif /* _OPENMP */
/* specifies whether double precision routines will be compiled or not */
#define LM_DBL_PREC
/* specifies whether single precision routines will be compiled or not */
#define LM_SNGL_PREC
/****************** End of configuration options, no changes necessary beyond this point ******************/
#ifdef __cplusplus
extern "C" {
#endif
/* work arrays size for ?levmar_der and ?levmar_dif functions.
* should be multiplied by sizeof(double) or sizeof(float) to be converted to bytes
*/
#define LM_DER_WORKSZ(npar, nmeas) (2*(nmeas) + 4*(npar) + (nmeas)*(npar) + (npar)*(npar))
#define LM_DIF_WORKSZ(npar, nmeas) (4*(nmeas) + 4*(npar) + (nmeas)*(npar) + (npar)*(npar))
/* work arrays size for ?levmar_bc_der and ?levmar_bc_dif functions.
* should be multiplied by sizeof(double) or sizeof(float) to be converted to bytes
*/
#define LM_BC_DER_WORKSZ(npar, nmeas) (2*(nmeas) + 4*(npar) + (nmeas)*(npar) + (npar)*(npar))
#define LM_BC_DIF_WORKSZ(npar, nmeas) LM_BC_DER_WORKSZ((npar), (nmeas)) /* LEVMAR_BC_DIF currently implemented using LEVMAR_BC_DER()! */
/* work arrays size for ?levmar_lec_der and ?levmar_lec_dif functions.
* should be multiplied by sizeof(double) or sizeof(float) to be converted to bytes
*/
#define LM_LEC_DER_WORKSZ(npar, nmeas, nconstr) LM_DER_WORKSZ((npar)-(nconstr), (nmeas))
#define LM_LEC_DIF_WORKSZ(npar, nmeas, nconstr) LM_DIF_WORKSZ((npar)-(nconstr), (nmeas))
/* work arrays size for ?levmar_blec_der and ?levmar_blec_dif functions.
* should be multiplied by sizeof(double) or sizeof(float) to be converted to bytes
*/
#define LM_BLEC_DER_WORKSZ(npar, nmeas, nconstr) LM_LEC_DER_WORKSZ((npar), (nmeas)+(npar), (nconstr))
#define LM_BLEC_DIF_WORKSZ(npar, nmeas, nconstr) LM_LEC_DIF_WORKSZ((npar), (nmeas)+(npar), (nconstr))
/* work arrays size for ?levmar_bleic_der and ?levmar_bleic_dif functions.
* should be multiplied by sizeof(double) or sizeof(float) to be converted to bytes
*/
#define LM_BLEIC_DER_WORKSZ(npar, nmeas, nconstr1, nconstr2) LM_BLEC_DER_WORKSZ((npar)+(nconstr2), (nmeas)+(nconstr2), (nconstr1)+(nconstr2))
#define LM_BLEIC_DIF_WORKSZ(npar, nmeas, nconstr1, nconstr2) LM_BLEC_DIF_WORKSZ((npar)+(nconstr2), (nmeas)+(nconstr2), (nconstr1)+(nconstr2))
#define LM_OPTS_SZ 5 /* max(4, 5) */
#define LM_INFO_SZ 10
#define LM_ERROR -1
#define LM_INIT_MU 1E-03
#define LM_STOP_THRESH 1E-17
#define LM_DIFF_DELTA 1E-06
#define LM_VERSION "2.6 (November 2011)"
#ifdef LM_DBL_PREC
/* double precision LM, with & without Jacobian */
/* unconstrained minimization */
extern int dlevmar_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, int itmax, double *opts,
double *info, double *work, double *covar, void *adata);
extern int dlevmar_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, int itmax, double *opts,
double *info, double *work, double *covar, void *adata);
/* box-constrained minimization */
extern int dlevmar_bc_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *dscl,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
extern int dlevmar_bc_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *dscl,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
#ifdef HAVE_LAPACK
/* linear equation constrained minimization */
extern int dlevmar_lec_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *A, double *b, int k,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
extern int dlevmar_lec_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *A, double *b, int k,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
/* box & linear equation constrained minimization */
extern int dlevmar_blec_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *A, double *b, int k, double *wghts,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
extern int dlevmar_blec_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *A, double *b, int k, double *wghts,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
/* box, linear equations & inequalities constrained minimization */
extern int dlevmar_bleic_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub,
double *A, double *b, int k1, double *C, double *d, int k2,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
extern int dlevmar_bleic_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub,
double *A, double *b, int k1, double *C, double *d, int k2,
int itmax, double *opts, double *info, double *work, double *covar, void *adata);
/* box & linear inequality constraints */
extern int dlevmar_blic_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *C, double *d, int k2,
int itmax, double opts[4], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
extern int dlevmar_blic_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *lb, double *ub, double *C, double *d, int k2,
int itmax, double opts[5], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
/* linear equation & inequality constraints */
extern int dlevmar_leic_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *A, double *b, int k1, double *C, double *d, int k2,
int itmax, double opts[4], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
extern int dlevmar_leic_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *A, double *b, int k1, double *C, double *d, int k2,
int itmax, double opts[5], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
/* linear inequality constraints */
extern int dlevmar_lic_der(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, double *x, int m, int n, double *C, double *d, int k2,
int itmax, double opts[4], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
extern int dlevmar_lic_dif(
void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *x, int m, int n, double *C, double *d, int k2,
int itmax, double opts[5], double info[LM_INFO_SZ], double *work, double *covar, void *adata);
#endif /* HAVE_LAPACK */
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
/* single precision LM, with & without Jacobian */
/* unconstrained minimization */
extern int slevmar_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, int itmax, float *opts,
float *info, float *work, float *covar, void *adata);
extern int slevmar_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, int itmax, float *opts,
float *info, float *work, float *covar, void *adata);
/* box-constrained minimization */
extern int slevmar_bc_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *dscl,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
extern int slevmar_bc_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *dscl,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
#ifdef HAVE_LAPACK
/* linear equation constrained minimization */
extern int slevmar_lec_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *A, float *b, int k,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
extern int slevmar_lec_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *A, float *b, int k,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
/* box & linear equation constrained minimization */
extern int slevmar_blec_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *A, float *b, int k, float *wghts,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
extern int slevmar_blec_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *A, float *b, int k, float *wghts,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
/* box, linear equations & inequalities constrained minimization */
extern int slevmar_bleic_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub,
float *A, float *b, int k1, float *C, float *d, int k2,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
extern int slevmar_bleic_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub,
float *A, float *b, int k1, float *C, float *d, int k2,
int itmax, float *opts, float *info, float *work, float *covar, void *adata);
/* box & linear inequality constraints */
extern int slevmar_blic_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *C, float *d, int k2,
int itmax, float opts[4], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
extern int slevmar_blic_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *lb, float *ub, float *C, float *d, int k2,
int itmax, float opts[5], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
/* linear equality & inequality constraints */
extern int slevmar_leic_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *A, float *b, int k1, float *C, float *d, int k2,
int itmax, float opts[4], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
extern int slevmar_leic_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *A, float *b, int k1, float *C, float *d, int k2,
int itmax, float opts[5], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
/* linear inequality constraints */
extern int slevmar_lic_der(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, float *x, int m, int n, float *C, float *d, int k2,
int itmax, float opts[4], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
extern int slevmar_lic_dif(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, float *C, float *d, int k2,
int itmax, float opts[5], float info[LM_INFO_SZ], float *work, float *covar, void *adata);
#endif /* HAVE_LAPACK */
#endif /* LM_SNGL_PREC */
/* linear system solvers */
#ifdef HAVE_LAPACK
#ifdef LM_DBL_PREC
extern int dAx_eq_b_QR(double *A, double *B, double *x, int m);
extern int dAx_eq_b_QRLS(double *A, double *B, double *x, int m, int n);
extern int dAx_eq_b_Chol(double *A, double *B, double *x, int m);
extern int dAx_eq_b_LU(double *A, double *B, double *x, int m);
extern int dAx_eq_b_SVD(double *A, double *B, double *x, int m);
extern int dAx_eq_b_BK(double *A, double *B, double *x, int m);
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
extern int sAx_eq_b_QR(float *A, float *B, float *x, int m);
extern int sAx_eq_b_QRLS(float *A, float *B, float *x, int m, int n);
extern int sAx_eq_b_Chol(float *A, float *B, float *x, int m);
extern int sAx_eq_b_LU(float *A, float *B, float *x, int m);
extern int sAx_eq_b_SVD(float *A, float *B, float *x, int m);
extern int sAx_eq_b_BK(float *A, float *B, float *x, int m);
#endif /* LM_SNGL_PREC */
#else /* no LAPACK */
#ifdef LM_DBL_PREC
extern int dAx_eq_b_LU_noLapack(double *A, double *B, double *x, int n);
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
extern int sAx_eq_b_LU_noLapack(float *A, float *B, float *x, int n);
#endif /* LM_SNGL_PREC */
#endif /* HAVE_LAPACK */
#ifdef HAVE_PLASMA
#ifdef LM_DBL_PREC
extern int dAx_eq_b_PLASMA_Chol(double *A, double *B, double *x, int m);
#endif
#ifdef LM_SNGL_PREC
extern int sAx_eq_b_PLASMA_Chol(float *A, float *B, float *x, int m);
#endif
extern void levmar_PLASMA_setnbcores(int cores);
#endif /* HAVE_PLASMA */
/* Jacobian verification, double & single precision */
#ifdef LM_DBL_PREC
extern void dlevmar_chkjac(
void (*func)(double *p, double *hx, int m, int n, void *adata),
void (*jacf)(double *p, double *j, int m, int n, void *adata),
double *p, int m, int n, void *adata, double *err);
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
extern void slevmar_chkjac(
void (*func)(float *p, float *hx, int m, int n, void *adata),
void (*jacf)(float *p, float *j, int m, int n, void *adata),
float *p, int m, int n, void *adata, float *err);
#endif /* LM_SNGL_PREC */
/* miscellaneous: standard deviation, coefficient of determination (R2),
* Pearson's correlation coefficient for best-fit parameters
*/
#ifdef LM_DBL_PREC
extern double dlevmar_stddev( double *covar, int m, int i);
extern double dlevmar_corcoef(double *covar, int m, int i, int j);
extern double dlevmar_R2(void (*func)(double *p, double *hx, int m, int n, void *adata), double *p, double *x, int m, int n, void *adata);
#endif /* LM_DBL_PREC */
#ifdef LM_SNGL_PREC
extern float slevmar_stddev( float *covar, int m, int i);
extern float slevmar_corcoef(float *covar, int m, int i, int j);
extern float slevmar_R2(void (*func)(float *p, float *hx, int m, int n, void *adata), float *p, float *x, int m, int n, void *adata);
extern void slevmar_locscale(
void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *x, int m, int n, void *adata,
int howto, float locscl[2], float **residptr);
extern int slevmar_outlid(float *r, int n, float thresh, float ls[2], char *outlmap);
#endif /* LM_SNGL_PREC */
#ifdef __cplusplus
}
#endif
#endif /* _LEVMAR_H_ */

View File

@@ -1,83 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/********************************************************************************
* Levenberg-Marquardt nonlinear minimization. The same core code is used with
* appropriate #defines to derive single and double precision versions, see
* also lm_core.c
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "levmar.h"
#include "compiler.h"
#include "misc.h"
#define EPSILON 1E-12
#define ONE_THIRD 0.3333333334 /* 1.0/3.0 */
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define LM_REAL_MAX FLT_MAX
#define LM_REAL_MIN -FLT_MAX
#define LM_REAL_EPSILON FLT_EPSILON
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "lm_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_EPSILON
#undef LM_REAL_MIN
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_REAL_MAX DBL_MAX
#define LM_REAL_MIN -DBL_MAX
#define LM_REAL_EPSILON DBL_EPSILON
#define LM_CNST(x) (x)
#include "lm_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_EPSILON
#undef LM_REAL_MIN
#undef LM_CNST
#endif /* LM_DBL_PREC */

View File

@@ -1,11 +0,0 @@
#ifndef _DEPR_LM_H_
#define _DEPR_LM_H_
#ifdef _MSC_VER
#pragma message("lm.h is deprecated, please use levmar.h instead!")
#else
#error lm.h is deprecated, please use levmar.h instead!
#endif /* _MSC_VER */
#endif /* _DEPR_LM_H_ */

View File

@@ -1,858 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef LM_REAL // not included by lm.c
#error This file should not be compiled directly!
#endif
/* precision-specific definitions */
#define LEVMAR_DER LM_ADD_PREFIX(levmar_der)
#define LEVMAR_DIF LM_ADD_PREFIX(levmar_dif)
#define LEVMAR_FDIF_FORW_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_forw_jac_approx)
#define LEVMAR_FDIF_CENT_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_cent_jac_approx)
#define LEVMAR_TRANS_MAT_MAT_MULT LM_ADD_PREFIX(levmar_trans_mat_mat_mult)
#define LEVMAR_L2NRMXMY LM_ADD_PREFIX(levmar_L2nrmxmy)
#define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)
#ifdef HAVE_LAPACK
#define AX_EQ_B_LU LM_ADD_PREFIX(Ax_eq_b_LU)
#define AX_EQ_B_CHOL LM_ADD_PREFIX(Ax_eq_b_Chol)
#define AX_EQ_B_QR LM_ADD_PREFIX(Ax_eq_b_QR)
#define AX_EQ_B_QRLS LM_ADD_PREFIX(Ax_eq_b_QRLS)
#define AX_EQ_B_SVD LM_ADD_PREFIX(Ax_eq_b_SVD)
#define AX_EQ_B_BK LM_ADD_PREFIX(Ax_eq_b_BK)
#else
#define AX_EQ_B_LU LM_ADD_PREFIX(Ax_eq_b_LU_noLapack)
#endif /* HAVE_LAPACK */
#ifdef HAVE_PLASMA
#define AX_EQ_B_PLASMA_CHOL LM_ADD_PREFIX(Ax_eq_b_PLASMA_Chol)
#endif
/*
* This function seeks the parameter vector p that best describes the measurements vector x.
* More precisely, given a vector function func : R^m --> R^n with n>=m,
* it finds p s.t. func(p) ~= x, i.e. the squared second order (i.e. L2) norm of
* e=x-func(p) is minimized.
*
* This function requires an analytic Jacobian. In case the latter is unavailable,
* use LEVMAR_DIF() bellow
*
* Returns the number of iterations (>=0) if successful, LM_ERROR if failed
*
* For more details, see K. Madsen, H.B. Nielsen and O. Tingleff's lecture notes on
* non-linear least squares at http://www.imm.dtu.dk/pubdb/views/edoc_download.php/3215/pdf/imm3215.pdf
*/
int LEVMAR_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata), /* function to evaluate the Jacobian \part x / \part p */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[4], /* I: minim. options [\mu, \epsilon1, \epsilon2, \epsilon3]. Respectively the scale factor for initial \mu,
* stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2. Set to NULL for defaults to be used
*/
LM_REAL info[LM_INFO_SZ],
/* O: information regarding the minimization. Set to NULL if don't care
* info[0]= ||e||_2 at initial p.
* info[1-4]=[ ||e||_2, ||J^T e||_inf, ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
* info[5]= # iterations,
* info[6]=reason for terminating: 1 - stopped by small gradient J^T e
* 2 - stopped by small Dp
* 3 - stopped by itmax
* 4 - singular matrix. Restart from current p with increased mu
* 5 - no further error reduction is possible. Restart with increased mu
* 6 - stopped by small ||e||_2
* 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
* info[7]= # function evaluations
* info[8]= # Jacobian evaluations
* info[9]= # linear systems solved, i.e. # attempts for reducing error
*/
LM_REAL *work, /* working memory at least LM_DER_WORKSZ() reals large, allocated if NULL */
LM_REAL *covar, /* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
void *adata) /* pointer to possibly additional data, passed uninterpreted to func & jacf.
* Set to NULL if not needed
*/
{
register int i, j, k, l;
int worksz, freework=0, issolved;
/* temp work arrays */
LM_REAL *e, /* nx1 */
*hx, /* \hat{x}_i, nx1 */
*jacTe, /* J^T e_i mx1 */
*jac, /* nxm */
*jacTjac, /* mxm */
*Dp, /* mx1 */
*diag_jacTjac, /* diagonal of J^T J, mx1 */
*pDp; /* p + Dp, mx1 */
register LM_REAL mu, /* damping constant */
tmp; /* mainly used in matrix & vector multiplications */
LM_REAL p_eL2, jacTe_inf, pDp_eL2; /* ||e(p)||_2, ||J^T e||_inf, ||e(p+Dp)||_2 */
LM_REAL p_L2, Dp_L2=LM_REAL_MAX, dF, dL;
LM_REAL tau, eps1, eps2, eps2_sq, eps3;
LM_REAL init_p_eL2;
int nu=2, nu2, stop=0, nfev, njev=0, nlss=0;
const int nm=n*m;
int (*linsolver)(LM_REAL *A, LM_REAL *B, LM_REAL *x, int m)=NULL;
mu=jacTe_inf=0.0; /* -Wall */
if(n<m){
fprintf(stderr, LCAT(LEVMAR_DER, "(): cannot solve a problem with fewer measurements [%d] than unknowns [%d]\n"), n, m);
return LM_ERROR;
}
if(!jacf){
fprintf(stderr, RCAT("No function specified for computing the Jacobian in ", LEVMAR_DER)
RCAT("().\nIf no such function is available, use ", LEVMAR_DIF) RCAT("() rather than ", LEVMAR_DER) "()\n");
return LM_ERROR;
}
if(opts){
tau=opts[0];
eps1=opts[1];
eps2=opts[2];
eps2_sq=opts[2]*opts[2];
eps3=opts[3];
}
else{ // use default values
tau=LM_CNST(LM_INIT_MU);
eps1=LM_CNST(LM_STOP_THRESH);
eps2=LM_CNST(LM_STOP_THRESH);
eps2_sq=LM_CNST(LM_STOP_THRESH)*LM_CNST(LM_STOP_THRESH);
eps3=LM_CNST(LM_STOP_THRESH);
}
if(!work){
worksz=LM_DER_WORKSZ(m, n); //2*n+4*m + n*m + m*m;
work=(LM_REAL *)malloc(worksz*sizeof(LM_REAL)); /* allocate a big chunk in one step */
if(!work){
fprintf(stderr, LCAT(LEVMAR_DER, "(): memory allocation request failed\n"));
return LM_ERROR;
}
freework=1;
}
/* set up work arrays */
e=work;
hx=e + n;
jacTe=hx + n;
jac=jacTe + m;
jacTjac=jac + nm;
Dp=jacTjac + m*m;
diag_jacTjac=Dp + m;
pDp=diag_jacTjac + m;
/* compute e=x - f(p) and its L2 norm */
(*func)(p, hx, m, n, adata); nfev=1;
/* ### e=x-hx, p_eL2=||e|| */
#if 1
p_eL2=LEVMAR_L2NRMXMY(e, x, hx, n);
#else
for(i=0, p_eL2=0.0; i<n; ++i){
e[i]=tmp=x[i]-hx[i];
p_eL2+=tmp*tmp;
}
#endif
init_p_eL2=p_eL2;
if(!LM_FINITE(p_eL2)) stop=7;
for(k=0; k<itmax && !stop; ++k){
/* Note that p and e have been updated at a previous iteration */
if(p_eL2<=eps3){ /* error is small */
stop=6;
break;
}
/* Compute the Jacobian J at p, J^T J, J^T e, ||J^T e||_inf and ||p||^2.
* Since J^T J is symmetric, its computation can be sped up by computing
* only its upper triangular part and copying it to the lower part
*/
(*jacf)(p, jac, m, n, adata); ++njev;
/* J^T J, J^T e */
if(nm<__BLOCKSZ__SQ){ // this is a small problem
/* J^T*J_ij = \sum_l J^T_il * J_lj = \sum_l J_li * J_lj.
* Thus, the product J^T J can be computed using an outer loop for
* l that adds J_li*J_lj to each element ij of the result. Note that
* with this scheme, the accesses to J and JtJ are always along rows,
* therefore induces less cache misses compared to the straightforward
* algorithm for computing the product (i.e., l loop is innermost one).
* A similar scheme applies to the computation of J^T e.
* However, for large minimization problems (i.e., involving a large number
* of unknowns and measurements) for which J/J^T J rows are too large to
* fit in the L1 cache, even this scheme incures many cache misses. In
* such cases, a cache-efficient blocking scheme is preferable.
*
* Thanks to John Nitao of Lawrence Livermore Lab for pointing out this
* performance problem.
*
* Note that the non-blocking algorithm is faster on small
* problems since in this case it avoids the overheads of blocking.
*/
/* looping downwards saves a few computations */
register int l;
register LM_REAL alpha, *jaclm, *jacTjacim;
for(i=m*m; i-->0; )
jacTjac[i]=0.0;
for(i=m; i-->0; )
jacTe[i]=0.0;
for(l=n; l-->0; ){
jaclm=jac+l*m;
for(i=m; i-->0; ){
jacTjacim=jacTjac+i*m;
alpha=jaclm[i]; //jac[l*m+i];
for(j=i+1; j-->0; ) /* j<=i computes lower triangular part only */
jacTjacim[j]+=jaclm[j]*alpha; //jacTjac[i*m+j]+=jac[l*m+j]*alpha
/* J^T e */
jacTe[i]+=alpha*e[l];
}
}
for(i=m; i-->0; ) /* copy to upper part */
for(j=i+1; j<m; ++j)
jacTjac[i*m+j]=jacTjac[j*m+i];
}
else{ // this is a large problem
/* Cache efficient computation of J^T J based on blocking
*/
LEVMAR_TRANS_MAT_MAT_MULT(jac, jacTjac, n, m);
/* cache efficient computation of J^T e */
for(i=0; i<m; ++i)
jacTe[i]=0.0;
for(i=0; i<n; ++i){
register LM_REAL *jacrow;
for(l=0, jacrow=jac+i*m, tmp=e[i]; l<m; ++l)
jacTe[l]+=jacrow[l]*tmp;
}
}
/* Compute ||J^T e||_inf and ||p||^2 */
for(i=0, p_L2=jacTe_inf=0.0; i<m; ++i){
if(jacTe_inf < (tmp=FABS(jacTe[i]))) jacTe_inf=tmp;
diag_jacTjac[i]=jacTjac[i*m+i]; /* save diagonal entries so that augmentation can be later canceled */
p_L2+=p[i]*p[i];
}
//p_L2=sqrt(p_L2);
#if 0
if(!(k%100)){
printf("Current estimate: ");
for(i=0; i<m; ++i)
printf("%.9g ", p[i]);
printf("-- errors %.9g %0.9g\n", jacTe_inf, p_eL2);
}
#endif
/* check for convergence */
if((jacTe_inf <= eps1)){
Dp_L2=0.0; /* no increment for p in this case */
stop=1;
break;
}
/* compute initial damping factor */
if(k==0){
for(i=0, tmp=LM_REAL_MIN; i<m; ++i)
if(diag_jacTjac[i]>tmp) tmp=diag_jacTjac[i]; /* find max diagonal element */
mu=tau*tmp;
}
/* determine increment using adaptive damping */
while(1){
/* augment normal equations */
for(i=0; i<m; ++i)
jacTjac[i*m+i]+=mu;
/* solve augmented equations */
#ifdef HAVE_LAPACK
/* 7 alternatives are available: LU, Cholesky + Cholesky with PLASMA, LDLt, 2 variants of QR decomposition and SVD.
* For matrices with dimensions of at least a few hundreds, the PLASMA implementation of Cholesky is the fastest.
* From the serial solvers, Cholesky is the fastest but might occasionally be inapplicable due to numerical round-off;
* QR is slower but more robust; SVD is the slowest but most robust; LU is quite robust but
* slower than LDLt; LDLt offers a good tradeoff between robustness and speed
*/
issolved=AX_EQ_B_BK(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_BK;
//issolved=AX_EQ_B_LU(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_LU;
//issolved=AX_EQ_B_CHOL(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_CHOL;
#ifdef HAVE_PLASMA
//issolved=AX_EQ_B_PLASMA_CHOL(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_PLASMA_CHOL;
#endif
//issolved=AX_EQ_B_QR(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_QR;
//issolved=AX_EQ_B_QRLS(jacTjac, jacTe, Dp, m, m); ++nlss; linsolver=(int (*)(LM_REAL *A, LM_REAL *B, LM_REAL *x, int m))AX_EQ_B_QRLS;
//issolved=AX_EQ_B_SVD(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_SVD;
#else
/* use the LU included with levmar */
issolved=AX_EQ_B_LU(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_LU;
#endif /* HAVE_LAPACK */
if(issolved){
/* compute p's new estimate and ||Dp||^2 */
for(i=0, Dp_L2=0.0; i<m; ++i){
pDp[i]=p[i] + (tmp=Dp[i]);
Dp_L2+=tmp*tmp;
}
//Dp_L2=sqrt(Dp_L2);
if(Dp_L2<=eps2_sq*p_L2){ /* relative change in p is small, stop */
//if(Dp_L2<=eps2*(p_L2 + eps2)){ /* relative change in p is small, stop */
stop=2;
break;
}
if(Dp_L2>=(p_L2+eps2)/(LM_CNST(EPSILON)*LM_CNST(EPSILON))){ /* almost singular */
//if(Dp_L2>=(p_L2+eps2)/LM_CNST(EPSILON)){ /* almost singular */
stop=4;
break;
}
(*func)(pDp, hx, m, n, adata); ++nfev; /* evaluate function at p + Dp */
/* compute ||e(pDp)||_2 */
/* ### hx=x-hx, pDp_eL2=||hx|| */
#if 1
pDp_eL2=LEVMAR_L2NRMXMY(hx, x, hx, n);
#else
for(i=0, pDp_eL2=0.0; i<n; ++i){
hx[i]=tmp=x[i]-hx[i];
pDp_eL2+=tmp*tmp;
}
#endif
if(!LM_FINITE(pDp_eL2)){ /* sum of squares is not finite, most probably due to a user error.
* This check makes sure that the inner loop does not run indefinitely.
* Thanks to Steve Danauskas for reporting such cases
*/
stop=7;
break;
}
for(i=0, dL=0.0; i<m; ++i)
dL+=Dp[i]*(mu*Dp[i]+jacTe[i]);
dF=p_eL2-pDp_eL2;
if(dL>0.0 && dF>0.0){ /* reduction in error, increment is accepted */
tmp=(LM_CNST(2.0)*dF/dL-LM_CNST(1.0));
tmp=LM_CNST(1.0)-tmp*tmp*tmp;
mu=mu*( (tmp>=LM_CNST(ONE_THIRD))? tmp : LM_CNST(ONE_THIRD) );
nu=2;
for(i=0 ; i<m; ++i) /* update p's estimate */
p[i]=pDp[i];
for(i=0; i<n; ++i) /* update e and ||e||_2 */
e[i]=hx[i];
p_eL2=pDp_eL2;
break;
}
}
/* if this point is reached, either the linear system could not be solved or
* the error did not reduce; in any case, the increment must be rejected
*/
mu*=nu;
nu2=nu<<1; // 2*nu;
if(nu2<=nu){ /* nu has wrapped around (overflown). Thanks to Frank Jordan for spotting this case */
stop=5;
break;
}
nu=nu2;
for(i=0; i<m; ++i) /* restore diagonal J^T J entries */
jacTjac[i*m+i]=diag_jacTjac[i];
} /* inner loop */
}
if(k>=itmax) stop=3;
for(i=0; i<m; ++i) /* restore diagonal J^T J entries */
jacTjac[i*m+i]=diag_jacTjac[i];
if(info){
info[0]=init_p_eL2;
info[1]=p_eL2;
info[2]=jacTe_inf;
info[3]=Dp_L2;
for(i=0, tmp=LM_REAL_MIN; i<m; ++i)
if(tmp<jacTjac[i*m+i]) tmp=jacTjac[i*m+i];
info[4]=mu/tmp;
info[5]=(LM_REAL)k;
info[6]=(LM_REAL)stop;
info[7]=(LM_REAL)nfev;
info[8]=(LM_REAL)njev;
info[9]=(LM_REAL)nlss;
}
/* covariance matrix */
if(covar){
LEVMAR_COVAR(jacTjac, covar, p_eL2, m, n);
}
if(freework) free(work);
#ifdef LINSOLVERS_RETAIN_MEMORY
if(linsolver) (*linsolver)(NULL, NULL, NULL, 0);
#endif
return (stop!=4 && stop!=7)? k : LM_ERROR;
}
/* Secant version of the LEVMAR_DER() function above: the Jacobian is approximated with
* the aid of finite differences (forward or central, see the comment for the opts argument)
*/
int LEVMAR_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[5], /* I: opts[0-4] = minim. options [\mu, \epsilon1, \epsilon2, \epsilon3, \delta]. Respectively the
* scale factor for initial \mu, stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2 and
* the step used in difference approximation to the Jacobian. Set to NULL for defaults to be used.
* If \delta<0, the Jacobian is approximated with central differences which are more accurate
* (but slower!) compared to the forward differences employed by default.
*/
LM_REAL info[LM_INFO_SZ],
/* O: information regarding the minimization. Set to NULL if don't care
* info[0]= ||e||_2 at initial p.
* info[1-4]=[ ||e||_2, ||J^T e||_inf, ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
* info[5]= # iterations,
* info[6]=reason for terminating: 1 - stopped by small gradient J^T e
* 2 - stopped by small Dp
* 3 - stopped by itmax
* 4 - singular matrix. Restart from current p with increased mu
* 5 - no further error reduction is possible. Restart with increased mu
* 6 - stopped by small ||e||_2
* 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
* info[7]= # function evaluations
* info[8]= # Jacobian evaluations
* info[9]= # linear systems solved, i.e. # attempts for reducing error
*/
LM_REAL *work, /* working memory at least LM_DIF_WORKSZ() reals large, allocated if NULL */
LM_REAL *covar, /* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
void *adata) /* pointer to possibly additional data, passed uninterpreted to func.
* Set to NULL if not needed
*/
{
register int i, j, k, l;
int worksz, freework=0, issolved;
/* temp work arrays */
LM_REAL *e, /* nx1 */
*hx, /* \hat{x}_i, nx1 */
*jacTe, /* J^T e_i mx1 */
*jac, /* nxm */
*jacTjac, /* mxm */
*Dp, /* mx1 */
*diag_jacTjac, /* diagonal of J^T J, mx1 */
*pDp, /* p + Dp, mx1 */
*wrk, /* nx1 */
*wrk2; /* nx1, used only for holding a temporary e vector and when differentiating with central differences */
int using_ffdif=1;
register LM_REAL mu, /* damping constant */
tmp; /* mainly used in matrix & vector multiplications */
LM_REAL p_eL2, jacTe_inf, pDp_eL2; /* ||e(p)||_2, ||J^T e||_inf, ||e(p+Dp)||_2 */
LM_REAL p_L2, Dp_L2=LM_REAL_MAX, dF, dL;
LM_REAL tau, eps1, eps2, eps2_sq, eps3, delta;
LM_REAL init_p_eL2;
int nu, nu2, stop=0, nfev, njap=0, nlss=0, K=(m>=10)? m: 10, updjac, updp=1, newjac;
const int nm=n*m;
int (*linsolver)(LM_REAL *A, LM_REAL *B, LM_REAL *x, int m)=NULL;
mu=jacTe_inf=p_L2=0.0; /* -Wall */
updjac=newjac=0; /* -Wall */
if(n<m){
fprintf(stderr, LCAT(LEVMAR_DIF, "(): cannot solve a problem with fewer measurements [%d] than unknowns [%d]\n"), n, m);
return LM_ERROR;
}
if(opts){
tau=opts[0];
eps1=opts[1];
eps2=opts[2];
eps2_sq=opts[2]*opts[2];
eps3=opts[3];
delta=opts[4];
if(delta<0.0){
delta=-delta; /* make positive */
using_ffdif=0; /* use central differencing */
}
}
else{ // use default values
tau=LM_CNST(LM_INIT_MU);
eps1=LM_CNST(LM_STOP_THRESH);
eps2=LM_CNST(LM_STOP_THRESH);
eps2_sq=LM_CNST(LM_STOP_THRESH)*LM_CNST(LM_STOP_THRESH);
eps3=LM_CNST(LM_STOP_THRESH);
delta=LM_CNST(LM_DIFF_DELTA);
}
if(!work){
worksz=LM_DIF_WORKSZ(m, n); //4*n+4*m + n*m + m*m;
work=(LM_REAL *)malloc(worksz*sizeof(LM_REAL)); /* allocate a big chunk in one step */
if(!work){
fprintf(stderr, LCAT(LEVMAR_DIF, "(): memory allocation request failed\n"));
return LM_ERROR;
}
freework=1;
}
/* set up work arrays */
e=work;
hx=e + n;
jacTe=hx + n;
jac=jacTe + m;
jacTjac=jac + nm;
Dp=jacTjac + m*m;
diag_jacTjac=Dp + m;
pDp=diag_jacTjac + m;
wrk=pDp + m;
wrk2=wrk + n;
/* compute e=x - f(p) and its L2 norm */
(*func)(p, hx, m, n, adata); nfev=1;
/* ### e=x-hx, p_eL2=||e|| */
#if 1
p_eL2=LEVMAR_L2NRMXMY(e, x, hx, n);
#else
for(i=0, p_eL2=0.0; i<n; ++i){
e[i]=tmp=x[i]-hx[i];
p_eL2+=tmp*tmp;
}
#endif
init_p_eL2=p_eL2;
if(!LM_FINITE(p_eL2)) stop=7;
nu=20; /* force computation of J */
for(k=0; k<itmax && !stop; ++k){
/* Note that p and e have been updated at a previous iteration */
if(p_eL2<=eps3){ /* error is small */
stop=6;
break;
}
/* Compute the Jacobian J at p, J^T J, J^T e, ||J^T e||_inf and ||p||^2.
* The symmetry of J^T J is again exploited for speed
*/
if((updp && nu>16) || updjac==K){ /* compute difference approximation to J */
if(using_ffdif){ /* use forward differences */
LEVMAR_FDIF_FORW_JAC_APPROX(func, p, hx, wrk, delta, jac, m, n, adata);
++njap; nfev+=m;
}
else{ /* use central differences */
LEVMAR_FDIF_CENT_JAC_APPROX(func, p, wrk, wrk2, delta, jac, m, n, adata);
++njap; nfev+=2*m;
}
nu=2; updjac=0; updp=0; newjac=1;
}
if(newjac){ /* Jacobian has changed, recompute J^T J, J^t e, etc */
newjac=0;
/* J^T J, J^T e */
if(nm<=__BLOCKSZ__SQ){ // this is a small problem
/* J^T*J_ij = \sum_l J^T_il * J_lj = \sum_l J_li * J_lj.
* Thus, the product J^T J can be computed using an outer loop for
* l that adds J_li*J_lj to each element ij of the result. Note that
* with this scheme, the accesses to J and JtJ are always along rows,
* therefore induces less cache misses compared to the straightforward
* algorithm for computing the product (i.e., l loop is innermost one).
* A similar scheme applies to the computation of J^T e.
* However, for large minimization problems (i.e., involving a large number
* of unknowns and measurements) for which J/J^T J rows are too large to
* fit in the L1 cache, even this scheme incures many cache misses. In
* such cases, a cache-efficient blocking scheme is preferable.
*
* Thanks to John Nitao of Lawrence Livermore Lab for pointing out this
* performance problem.
*
* Note that the non-blocking algorithm is faster on small
* problems since in this case it avoids the overheads of blocking.
*/
register int l;
register LM_REAL alpha, *jaclm, *jacTjacim;
/* looping downwards saves a few computations */
for(i=m*m; i-->0; )
jacTjac[i]=0.0;
for(i=m; i-->0; )
jacTe[i]=0.0;
for(l=n; l-->0; ){
jaclm=jac+l*m;
for(i=m; i-->0; ){
jacTjacim=jacTjac+i*m;
alpha=jaclm[i]; //jac[l*m+i];
for(j=i+1; j-->0; ) /* j<=i computes lower triangular part only */
jacTjacim[j]+=jaclm[j]*alpha; //jacTjac[i*m+j]+=jac[l*m+j]*alpha
/* J^T e */
jacTe[i]+=alpha*e[l];
}
}
for(i=m; i-->0; ) /* copy to upper part */
for(j=i+1; j<m; ++j)
jacTjac[i*m+j]=jacTjac[j*m+i];
}
else{ // this is a large problem
/* Cache efficient computation of J^T J based on blocking
*/
LEVMAR_TRANS_MAT_MAT_MULT(jac, jacTjac, n, m);
/* cache efficient computation of J^T e */
for(i=0; i<m; ++i)
jacTe[i]=0.0;
for(i=0; i<n; ++i){
register LM_REAL *jacrow;
for(l=0, jacrow=jac+i*m, tmp=e[i]; l<m; ++l)
jacTe[l]+=jacrow[l]*tmp;
}
}
/* Compute ||J^T e||_inf and ||p||^2 */
for(i=0, p_L2=jacTe_inf=0.0; i<m; ++i){
if(jacTe_inf < (tmp=FABS(jacTe[i]))) jacTe_inf=tmp;
diag_jacTjac[i]=jacTjac[i*m+i]; /* save diagonal entries so that augmentation can be later canceled */
p_L2+=p[i]*p[i];
}
//p_L2=sqrt(p_L2);
}
#if 0
if(!(k%100)){
printf("Current estimate: ");
for(i=0; i<m; ++i)
printf("%.9g ", p[i]);
printf("-- errors %.9g %0.9g\n", jacTe_inf, p_eL2);
}
#endif
/* check for convergence */
if((jacTe_inf <= eps1)){
Dp_L2=0.0; /* no increment for p in this case */
stop=1;
break;
}
/* compute initial damping factor */
if(k==0){
for(i=0, tmp=LM_REAL_MIN; i<m; ++i)
if(diag_jacTjac[i]>tmp) tmp=diag_jacTjac[i]; /* find max diagonal element */
mu=tau*tmp;
}
/* determine increment using adaptive damping */
/* augment normal equations */
for(i=0; i<m; ++i)
jacTjac[i*m+i]+=mu;
/* solve augmented equations */
#ifdef HAVE_LAPACK
/* 7 alternatives are available: LU, Cholesky + Cholesky with PLASMA, LDLt, 2 variants of QR decomposition and SVD.
* For matrices with dimensions of at least a few hundreds, the PLASMA implementation of Cholesky is the fastest.
* From the serial solvers, Cholesky is the fastest but might occasionally be inapplicable due to numerical round-off;
* QR is slower but more robust; SVD is the slowest but most robust; LU is quite robust but
* slower than LDLt; LDLt offers a good tradeoff between robustness and speed
*/
issolved=AX_EQ_B_BK(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_BK;
//issolved=AX_EQ_B_LU(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_LU;
//issolved=AX_EQ_B_CHOL(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_CHOL;
#ifdef HAVE_PLASMA
//issolved=AX_EQ_B_PLASMA_CHOL(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_PLASMA_CHOL;
#endif
//issolved=AX_EQ_B_QR(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_QR;
//issolved=AX_EQ_B_QRLS(jacTjac, jacTe, Dp, m, m); ++nlss; linsolver=(int (*)(LM_REAL *A, LM_REAL *B, LM_REAL *x, int m))AX_EQ_B_QRLS;
//issolved=AX_EQ_B_SVD(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_SVD;
#else
/* use the LU included with levmar */
issolved=AX_EQ_B_LU(jacTjac, jacTe, Dp, m); ++nlss; linsolver=AX_EQ_B_LU;
#endif /* HAVE_LAPACK */
if(issolved){
/* compute p's new estimate and ||Dp||^2 */
for(i=0, Dp_L2=0.0; i<m; ++i){
pDp[i]=p[i] + (tmp=Dp[i]);
Dp_L2+=tmp*tmp;
}
//Dp_L2=sqrt(Dp_L2);
if(Dp_L2<=eps2_sq*p_L2){ /* relative change in p is small, stop */
//if(Dp_L2<=eps2*(p_L2 + eps2)){ /* relative change in p is small, stop */
stop=2;
break;
}
if(Dp_L2>=(p_L2+eps2)/(LM_CNST(EPSILON)*LM_CNST(EPSILON))){ /* almost singular */
//if(Dp_L2>=(p_L2+eps2)/LM_CNST(EPSILON)){ /* almost singular */
stop=4;
break;
}
(*func)(pDp, wrk, m, n, adata); ++nfev; /* evaluate function at p + Dp */
/* compute ||e(pDp)||_2 */
/* ### wrk2=x-wrk, pDp_eL2=||wrk2|| */
#if 1
pDp_eL2=LEVMAR_L2NRMXMY(wrk2, x, wrk, n);
#else
for(i=0, pDp_eL2=0.0; i<n; ++i){
wrk2[i]=tmp=x[i]-wrk[i];
pDp_eL2+=tmp*tmp;
}
#endif
if(!LM_FINITE(pDp_eL2)){ /* sum of squares is not finite, most probably due to a user error.
* This check makes sure that the loop terminates early in the case
* of invalid input. Thanks to Steve Danauskas for suggesting it
*/
stop=7;
break;
}
dF=p_eL2-pDp_eL2;
if(updp || dF>0){ /* update jac */
for(i=0; i<n; ++i){
for(l=0, tmp=0.0; l<m; ++l)
tmp+=jac[i*m+l]*Dp[l]; /* (J * Dp)[i] */
tmp=(wrk[i] - hx[i] - tmp)/Dp_L2; /* (f(p+dp)[i] - f(p)[i] - (J * Dp)[i])/(dp^T*dp) */
for(j=0; j<m; ++j)
jac[i*m+j]+=tmp*Dp[j];
}
++updjac;
newjac=1;
}
for(i=0, dL=0.0; i<m; ++i)
dL+=Dp[i]*(mu*Dp[i]+jacTe[i]);
if(dL>0.0 && dF>0.0){ /* reduction in error, increment is accepted */
tmp=(LM_CNST(2.0)*dF/dL-LM_CNST(1.0));
tmp=LM_CNST(1.0)-tmp*tmp*tmp;
mu=mu*( (tmp>=LM_CNST(ONE_THIRD))? tmp : LM_CNST(ONE_THIRD) );
nu=2;
for(i=0 ; i<m; ++i) /* update p's estimate */
p[i]=pDp[i];
for(i=0; i<n; ++i){ /* update e, hx and ||e||_2 */
e[i]=wrk2[i]; //x[i]-wrk[i];
hx[i]=wrk[i];
}
p_eL2=pDp_eL2;
updp=1;
continue;
}
}
/* if this point is reached, either the linear system could not be solved or
* the error did not reduce; in any case, the increment must be rejected
*/
mu*=nu;
nu2=nu<<1; // 2*nu;
if(nu2<=nu){ /* nu has wrapped around (overflown). Thanks to Frank Jordan for spotting this case */
stop=5;
break;
}
nu=nu2;
for(i=0; i<m; ++i) /* restore diagonal J^T J entries */
jacTjac[i*m+i]=diag_jacTjac[i];
}
if(k>=itmax) stop=3;
for(i=0; i<m; ++i) /* restore diagonal J^T J entries */
jacTjac[i*m+i]=diag_jacTjac[i];
if(info){
info[0]=init_p_eL2;
info[1]=p_eL2;
info[2]=jacTe_inf;
info[3]=Dp_L2;
for(i=0, tmp=LM_REAL_MIN; i<m; ++i)
if(tmp<jacTjac[i*m+i]) tmp=jacTjac[i*m+i];
info[4]=mu/tmp;
info[5]=(LM_REAL)k;
info[6]=(LM_REAL)stop;
info[7]=(LM_REAL)nfev;
info[8]=(LM_REAL)njap;
info[9]=(LM_REAL)nlss;
}
/* covariance matrix */
if(covar){
LEVMAR_COVAR(jacTjac, covar, p_eL2, m, n);
}
if(freework) free(work);
#ifdef LINSOLVERS_RETAIN_MEMORY
if(linsolver) (*linsolver)(NULL, NULL, NULL, 0);
#endif
return (stop!=4 && stop!=7)? k : LM_ERROR;
}
/* undefine everything. THIS MUST REMAIN AT THE END OF THE FILE */
#undef LEVMAR_DER
#undef LEVMAR_DIF
#undef LEVMAR_FDIF_FORW_JAC_APPROX
#undef LEVMAR_FDIF_CENT_JAC_APPROX
#undef LEVMAR_COVAR
#undef LEVMAR_TRANS_MAT_MAT_MULT
#undef LEVMAR_L2NRMXMY
#undef AX_EQ_B_LU
#undef AX_EQ_B_CHOL
#undef AX_EQ_B_PLASMA_CHOL
#undef AX_EQ_B_QR
#undef AX_EQ_B_QRLS
#undef AX_EQ_B_SVD
#undef AX_EQ_B_BK

View File

@@ -1,87 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-05 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/********************************************************************************
* Box-constrained Levenberg-Marquardt nonlinear minimization. The same core code
* is used with appropriate #defines to derive single and double precision versions,
* see also lmbc_core.c
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "levmar.h"
#include "compiler.h"
#include "misc.h"
#define EPSILON 1E-12
#define ONE_THIRD 0.3333333334 /* 1.0/3.0 */
#define _LSITMAX_ 150 /* max #iterations for line search */
#define _POW_ 2.1
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define LM_REAL_MAX FLT_MAX
#define LM_REAL_MIN -FLT_MAX
#define LM_REAL_EPSILON FLT_EPSILON
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "lmbc_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef LM_REAL_EPSILON
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_REAL_MAX DBL_MAX
#define LM_REAL_MIN -DBL_MAX
#define LM_REAL_EPSILON DBL_EPSILON
#define LM_CNST(x) (x)
#include "lmbc_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef LM_REAL_EPSILON
#undef LM_CNST
#endif /* LM_DBL_PREC */

File diff suppressed because it is too large Load Diff

View File

@@ -1,87 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-06 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/********************************************************************************
* combined box and linear equation constraints Levenberg-Marquardt nonlinear
* minimization. The same core code is used with appropriate #defines to derive
* single and double precision versions, see also lmblec_core.c
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "levmar.h"
#include "misc.h"
#ifndef HAVE_LAPACK
#ifdef _MSC_VER
#pragma message("Combined box and linearly constrained optimization requires LAPACK and was not compiled!")
#else
#warning Combined box and linearly constrained optimization requires LAPACK and was not compiled!
#endif // _MSC_VER
#else // LAPACK present
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define LM_REAL_MAX FLT_MAX
#define LM_REAL_MIN -FLT_MAX
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "lmblec_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_REAL_MAX DBL_MAX
#define LM_REAL_MIN -DBL_MAX
#define LM_CNST(x) (x)
#include "lmblec_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef LM_CNST
#endif /* LM_DBL_PREC */
#endif /* HAVE_LAPACK */

View File

@@ -1,413 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-06 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
* This file implements combined box and linear equation constraints.
*
* Note that the algorithm implementing linearly constrained minimization does
* so by a change in parameters that transforms the original program into an
* unconstrained one. To employ the same idea for implementing box & linear
* constraints would require the transformation of box constraints on the
* original parameters to box constraints for the new parameter set. This
* being impossible, a different approach is used here for finding the minimum.
* The trick is to remove the box constraints by augmenting the function to
* be fitted with penalty terms and then solve the resulting problem (which
* involves linear constrains only) with the functions in lmlec.c
*
* More specifically, for the constraint a<=x[i]<=b to hold, the term C[i]=
* (2*x[i]-(a+b))/(b-a) should be within [-1, 1]. This is enforced by adding
* the penalty term w[i]*max((C[i])^2-1, 0) to the objective function, where
* w[i] is a large weight. In the case of constraints of the form a<=x[i],
* the term C[i]=a-x[i] has to be non positive, thus the penalty term is
* w[i]*max(C[i], 0). If x[i]<=b, C[i]=x[i]-b has to be non negative and
* the penalty is w[i]*max(C[i], 0). The derivatives needed for the Jacobian
* are as follows:
* For the constraint a<=x[i]<=b: 4*(2*x[i]-(a+b))/(b-a)^2 if x[i] not in [a, b],
* 0 otherwise
* For the constraint a<=x[i]: -1 if x[i]<=a, 0 otherwise
* For the constraint x[i]<=b: 1 if b<=x[i], 0 otherwise
*
* Note that for the above to work, the weights w[i] should be large enough;
* depending on your minimization problem, the default values might need some
* tweaking (see arg "wghts" below).
*******************************************************************************/
#ifndef LM_REAL // not included by lmblec.c
#error This file should not be compiled directly!
#endif
#define __MAX__(x, y) (((x)>=(y))? (x) : (y))
#define __BC_WEIGHT__ LM_CNST(1E+04)
#define __BC_INTERVAL__ 0
#define __BC_LOW__ 1
#define __BC_HIGH__ 2
/* precision-specific definitions */
#define LEVMAR_BOX_CHECK LM_ADD_PREFIX(levmar_box_check)
#define LMBLEC_DATA LM_ADD_PREFIX(lmblec_data)
#define LMBLEC_FUNC LM_ADD_PREFIX(lmblec_func)
#define LMBLEC_JACF LM_ADD_PREFIX(lmblec_jacf)
#define LEVMAR_LEC_DER LM_ADD_PREFIX(levmar_lec_der)
#define LEVMAR_LEC_DIF LM_ADD_PREFIX(levmar_lec_dif)
#define LEVMAR_BLEC_DER LM_ADD_PREFIX(levmar_blec_der)
#define LEVMAR_BLEC_DIF LM_ADD_PREFIX(levmar_blec_dif)
#define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)
struct LMBLEC_DATA{
LM_REAL *x, *lb, *ub, *w;
int *bctype;
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata);
void (*jacf)(LM_REAL *p, LM_REAL *jac, int m, int n, void *adata);
void *adata;
};
/* augmented measurements */
static void LMBLEC_FUNC(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata)
{
struct LMBLEC_DATA *data=(struct LMBLEC_DATA *)adata;
int nn;
register int i, j, *typ;
register LM_REAL *lb, *ub, *w, tmp;
nn=n-m;
lb=data->lb;
ub=data->ub;
w=data->w;
typ=data->bctype;
(*(data->func))(p, hx, m, nn, data->adata);
for(i=nn, j=0; i<n; ++i, ++j){
switch(typ[j]){
case __BC_INTERVAL__:
tmp=(LM_CNST(2.0)*p[j]-(lb[j]+ub[j]))/(ub[j]-lb[j]);
hx[i]=w[j]*__MAX__(tmp*tmp-LM_CNST(1.0), LM_CNST(0.0));
break;
case __BC_LOW__:
hx[i]=w[j]*__MAX__(lb[j]-p[j], LM_CNST(0.0));
break;
case __BC_HIGH__:
hx[i]=w[j]*__MAX__(p[j]-ub[j], LM_CNST(0.0));
break;
}
}
}
/* augmented Jacobian */
static void LMBLEC_JACF(LM_REAL *p, LM_REAL *jac, int m, int n, void *adata)
{
struct LMBLEC_DATA *data=(struct LMBLEC_DATA *)adata;
int nn, *typ;
register int i, j;
register LM_REAL *lb, *ub, *w, tmp;
nn=n-m;
lb=data->lb;
ub=data->ub;
w=data->w;
typ=data->bctype;
(*(data->jacf))(p, jac, m, nn, data->adata);
/* clear all extra rows */
for(i=nn*m; i<n*m; ++i)
jac[i]=0.0;
for(i=nn, j=0; i<n; ++i, ++j){
switch(typ[j]){
case __BC_INTERVAL__:
if(lb[j]<=p[j] && p[j]<=ub[j])
continue; // corresp. jac element already 0
/* out of interval */
tmp=ub[j]-lb[j];
tmp=LM_CNST(4.0)*(LM_CNST(2.0)*p[j]-(lb[j]+ub[j]))/(tmp*tmp);
jac[i*m+j]=w[j]*tmp;
break;
case __BC_LOW__: // (lb[j]<=p[j])? 0.0 : -1.0;
if(lb[j]<=p[j])
continue; // corresp. jac element already 0
/* smaller than lower bound */
jac[i*m+j]=-w[j];
break;
case __BC_HIGH__: // (p[j]<=ub[j])? 0.0 : 1.0;
if(p[j]<=ub[j])
continue; // corresp. jac element already 0
/* greater than upper bound */
jac[i*m+j]=w[j];
break;
}
}
}
/*
* This function seeks the parameter vector p that best describes the measurements
* vector x under box & linear constraints.
* More precisely, given a vector function func : R^m --> R^n with n>=m,
* it finds p s.t. func(p) ~= x, i.e. the squared second order (i.e. L2) norm of
* e=x-func(p) is minimized under the constraints lb[i]<=p[i]<=ub[i] and A p=b;
* A is kxm, b kx1. Note that this function DOES NOT check the satisfiability of
* the specified box and linear equation constraints.
* If no lower bound constraint applies for p[i], use -DBL_MAX/-FLT_MAX for lb[i];
* If no upper bound constraint applies for p[i], use DBL_MAX/FLT_MAX for ub[i].
*
* This function requires an analytic Jacobian. In case the latter is unavailable,
* use LEVMAR_BLEC_DIF() bellow
*
* Returns the number of iterations (>=0) if successful, LM_ERROR if failed
*
* For more details on the algorithm implemented by this function, please refer to
* the comments in the top of this file.
*
*/
int LEVMAR_BLEC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata), /* function to evaluate the Jacobian \part x / \part p */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *lb, /* I: vector of lower bounds. If NULL, no lower bounds apply */
LM_REAL *ub, /* I: vector of upper bounds. If NULL, no upper bounds apply */
LM_REAL *A, /* I: constraints matrix, kxm */
LM_REAL *b, /* I: right hand constraints vector, kx1 */
int k, /* I: number of constraints (i.e. A's #rows) */
LM_REAL *wghts, /* mx1 weights for penalty terms, defaults used if NULL */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[4], /* I: minim. options [\mu, \epsilon1, \epsilon2, \epsilon3]. Respectively the scale factor for initial \mu,
* stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2. Set to NULL for defaults to be used
*/
LM_REAL info[LM_INFO_SZ],
/* O: information regarding the minimization. Set to NULL if don't care
* info[0]= ||e||_2 at initial p.
* info[1-4]=[ ||e||_2, ||J^T e||_inf, ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
* info[5]= # iterations,
* info[6]=reason for terminating: 1 - stopped by small gradient J^T e
* 2 - stopped by small Dp
* 3 - stopped by itmax
* 4 - singular matrix. Restart from current p with increased mu
* 5 - no further error reduction is possible. Restart with increased mu
* 6 - stopped by small ||e||_2
* 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
* info[7]= # function evaluations
* info[8]= # Jacobian evaluations
* info[9]= # linear systems solved, i.e. # attempts for reducing error
*/
LM_REAL *work, /* working memory at least LM_BLEC_DER_WORKSZ() reals large, allocated if NULL */
LM_REAL *covar, /* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
void *adata) /* pointer to possibly additional data, passed uninterpreted to func & jacf.
* Set to NULL if not needed
*/
{
struct LMBLEC_DATA data;
int ret;
LM_REAL locinfo[LM_INFO_SZ];
register int i;
if(!jacf){
fprintf(stderr, RCAT("No function specified for computing the Jacobian in ", LEVMAR_BLEC_DER)
RCAT("().\nIf no such function is available, use ", LEVMAR_BLEC_DIF) RCAT("() rather than ", LEVMAR_BLEC_DER) "()\n");
return LM_ERROR;
}
if(!lb && !ub){
fprintf(stderr, RCAT(LCAT(LEVMAR_BLEC_DER, "(): lower and upper bounds for box constraints cannot be both NULL, use "),
LEVMAR_LEC_DER) "() in this case!\n");
return LM_ERROR;
}
if(!LEVMAR_BOX_CHECK(lb, ub, m)){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): at least one lower bound exceeds the upper one\n"));
return LM_ERROR;
}
/* measurement vector needs to be extended by m */
if(x){ /* nonzero x */
data.x=(LM_REAL *)malloc((n+m)*sizeof(LM_REAL));
if(!data.x){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): memory allocation request #1 failed\n"));
return LM_ERROR;
}
for(i=0; i<n; ++i)
data.x[i]=x[i];
for(i=n; i<n+m; ++i)
data.x[i]=0.0;
}
else
data.x=NULL;
data.w=(LM_REAL *)malloc(m*sizeof(LM_REAL) + m*sizeof(int)); /* should be arranged in that order for proper doubles alignment */
if(!data.w){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): memory allocation request #2 failed\n"));
if(data.x) free(data.x);
return LM_ERROR;
}
data.bctype=(int *)(data.w+m);
/* note: at this point, one of lb, ub are not NULL */
for(i=0; i<m; ++i){
data.w[i]=(!wghts)? __BC_WEIGHT__ : wghts[i];
if(!lb) data.bctype[i]=__BC_HIGH__;
else if(!ub) data.bctype[i]=__BC_LOW__;
else if(ub[i]!=LM_REAL_MAX && lb[i]!=LM_REAL_MIN) data.bctype[i]=__BC_INTERVAL__;
else if(lb[i]!=LM_REAL_MIN) data.bctype[i]=__BC_LOW__;
else data.bctype[i]=__BC_HIGH__;
}
data.lb=lb;
data.ub=ub;
data.func=func;
data.jacf=jacf;
data.adata=adata;
if(!info) info=locinfo; /* make sure that LEVMAR_LEC_DER() is called with non-null info */
ret=LEVMAR_LEC_DER(LMBLEC_FUNC, LMBLEC_JACF, p, data.x, m, n+m, A, b, k, itmax, opts, info, work, covar, (void *)&data);
if(data.x) free(data.x);
free(data.w);
return ret;
}
/* Similar to the LEVMAR_BLEC_DER() function above, except that the Jacobian is approximated
* with the aid of finite differences (forward or central, see the comment for the opts argument)
*/
int LEVMAR_BLEC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *lb, /* I: vector of lower bounds. If NULL, no lower bounds apply */
LM_REAL *ub, /* I: vector of upper bounds. If NULL, no upper bounds apply */
LM_REAL *A, /* I: constraints matrix, kxm */
LM_REAL *b, /* I: right hand constraints vector, kx1 */
int k, /* I: number of constraints (i.e. A's #rows) */
LM_REAL *wghts, /* mx1 weights for penalty terms, defaults used if NULL */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[5], /* I: opts[0-3] = minim. options [\mu, \epsilon1, \epsilon2, \epsilon3, \delta]. Respectively the
* scale factor for initial \mu, stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2 and
* the step used in difference approximation to the Jacobian. Set to NULL for defaults to be used.
* If \delta<0, the Jacobian is approximated with central differences which are more accurate
* (but slower!) compared to the forward differences employed by default.
*/
LM_REAL info[LM_INFO_SZ],
/* O: information regarding the minimization. Set to NULL if don't care
* info[0]= ||e||_2 at initial p.
* info[1-4]=[ ||e||_2, ||J^T e||_inf, ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
* info[5]= # iterations,
* info[6]=reason for terminating: 1 - stopped by small gradient J^T e
* 2 - stopped by small Dp
* 3 - stopped by itmax
* 4 - singular matrix. Restart from current p with increased mu
* 5 - no further error reduction is possible. Restart with increased mu
* 6 - stopped by small ||e||_2
* 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
* info[7]= # function evaluations
* info[8]= # Jacobian evaluations
* info[9]= # linear systems solved, i.e. # attempts for reducing error
*/
LM_REAL *work, /* working memory at least LM_BLEC_DIF_WORKSZ() reals large, allocated if NULL */
LM_REAL *covar, /* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
void *adata) /* pointer to possibly additional data, passed uninterpreted to func.
* Set to NULL if not needed
*/
{
struct LMBLEC_DATA data;
int ret;
register int i;
LM_REAL locinfo[LM_INFO_SZ];
if(!lb && !ub){
fprintf(stderr, RCAT(LCAT(LEVMAR_BLEC_DIF, "(): lower and upper bounds for box constraints cannot be both NULL, use "),
LEVMAR_LEC_DIF) "() in this case!\n");
return LM_ERROR;
}
if(!LEVMAR_BOX_CHECK(lb, ub, m)){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): at least one lower bound exceeds the upper one\n"));
return LM_ERROR;
}
/* measurement vector needs to be extended by m */
if(x){ /* nonzero x */
data.x=(LM_REAL *)malloc((n+m)*sizeof(LM_REAL));
if(!data.x){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): memory allocation request #1 failed\n"));
return LM_ERROR;
}
for(i=0; i<n; ++i)
data.x[i]=x[i];
for(i=n; i<n+m; ++i)
data.x[i]=0.0;
}
else
data.x=NULL;
data.w=(LM_REAL *)malloc(m*sizeof(LM_REAL) + m*sizeof(int)); /* should be arranged in that order for proper doubles alignment */
if(!data.w){
fprintf(stderr, LCAT(LEVMAR_BLEC_DER, "(): memory allocation request #2 failed\n"));
if(data.x) free(data.x);
return LM_ERROR;
}
data.bctype=(int *)(data.w+m);
/* note: at this point, one of lb, ub are not NULL */
for(i=0; i<m; ++i){
data.w[i]=(!wghts)? __BC_WEIGHT__ : wghts[i];
if(!lb) data.bctype[i]=__BC_HIGH__;
else if(!ub) data.bctype[i]=__BC_LOW__;
else if(ub[i]!=LM_REAL_MAX && lb[i]!=LM_REAL_MIN) data.bctype[i]=__BC_INTERVAL__;
else if(lb[i]!=LM_REAL_MIN) data.bctype[i]=__BC_LOW__;
else data.bctype[i]=__BC_HIGH__;
}
data.lb=lb;
data.ub=ub;
data.func=func;
data.jacf=NULL;
data.adata=adata;
if(!info) info=locinfo; /* make sure that LEVMAR_LEC_DIF() is called with non-null info */
ret=LEVMAR_LEC_DIF(LMBLEC_FUNC, p, data.x, m, n+m, A, b, k, itmax, opts, info, work, covar, (void *)&data);
if(data.x) free(data.x);
free(data.w);
return ret;
}
/* undefine all. THIS MUST REMAIN AT THE END OF THE FILE */
#undef LEVMAR_BOX_CHECK
#undef LMBLEC_DATA
#undef LMBLEC_FUNC
#undef LMBLEC_JACF
#undef LEVMAR_COVAR
#undef LEVMAR_LEC_DER
#undef LEVMAR_LEC_DIF
#undef LEVMAR_BLEC_DER
#undef LEVMAR_BLEC_DIF

View File

@@ -1,89 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2009 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
* Wrappers for linear inequality constrained Levenberg-Marquardt minimization.
* The same core code is used with appropriate #defines to derive single and
* double precision versions, see also lmbleic_core.c
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "levmar.h"
#include "misc.h"
#ifndef HAVE_LAPACK
#ifdef _MSC_VER
#pragma message("Linear inequalities constrained optimization requires LAPACK and was not compiled!")
#else
#warning Linear inequalities constrained optimization requires LAPACK and was not compiled!
#endif // _MSC_VER
#else // LAPACK present
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define LM_REAL_MAX FLT_MAX
#define LM_REAL_MIN -FLT_MAX
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "lmbleic_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_REAL_MAX DBL_MAX
#define LM_REAL_MIN -DBL_MAX
#define LM_CNST(x) (x)
#include "lmbleic_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_MAX
#undef LM_REAL_MIN
#undef LM_CNST
#endif /* LM_DBL_PREC */
#endif /* HAVE_LAPACK */

View File

@@ -1,506 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2009 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef LM_REAL // not included by lmbleic.c
#error This file should not be compiled directly!
#endif
/* precision-specific definitions */
#define LMBLEIC_DATA LM_ADD_PREFIX(lmbleic_data)
#define LMBLEIC_ELIM LM_ADD_PREFIX(lmbleic_elim)
#define LMBLEIC_FUNC LM_ADD_PREFIX(lmbleic_func)
#define LMBLEIC_JACF LM_ADD_PREFIX(lmbleic_jacf)
#define LEVMAR_BLEIC_DER LM_ADD_PREFIX(levmar_bleic_der)
#define LEVMAR_BLEIC_DIF LM_ADD_PREFIX(levmar_bleic_dif)
#define LEVMAR_BLIC_DER LM_ADD_PREFIX(levmar_blic_der)
#define LEVMAR_BLIC_DIF LM_ADD_PREFIX(levmar_blic_dif)
#define LEVMAR_LEIC_DER LM_ADD_PREFIX(levmar_leic_der)
#define LEVMAR_LEIC_DIF LM_ADD_PREFIX(levmar_leic_dif)
#define LEVMAR_LIC_DER LM_ADD_PREFIX(levmar_lic_der)
#define LEVMAR_LIC_DIF LM_ADD_PREFIX(levmar_lic_dif)
#define LEVMAR_BLEC_DER LM_ADD_PREFIX(levmar_blec_der)
#define LEVMAR_BLEC_DIF LM_ADD_PREFIX(levmar_blec_dif)
#define LEVMAR_TRANS_MAT_MAT_MULT LM_ADD_PREFIX(levmar_trans_mat_mat_mult)
#define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)
#define LEVMAR_FDIF_FORW_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_forw_jac_approx)
struct LMBLEIC_DATA{
LM_REAL *jac;
int nineqcnstr; // #inequality constraints
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata);
void (*jacf)(LM_REAL *p, LM_REAL *jac, int m, int n, void *adata);
void *adata;
};
/* wrapper ensuring that the user-supplied function is called with the right number of variables (i.e. m) */
static void LMBLEIC_FUNC(LM_REAL *pext, LM_REAL *hx, int mm, int n, void *adata)
{
struct LMBLEIC_DATA *data=(struct LMBLEIC_DATA *)adata;
int m;
m=mm-data->nineqcnstr;
(*(data->func))(pext, hx, m, n, data->adata);
}
/* wrapper for computing the Jacobian at pext. The Jacobian is nxmm */
static void LMBLEIC_JACF(LM_REAL *pext, LM_REAL *jacext, int mm, int n, void *adata)
{
struct LMBLEIC_DATA *data=(struct LMBLEIC_DATA *)adata;
int m;
register int i, j;
LM_REAL *jac, *jacim, *jacextimm;
m=mm-data->nineqcnstr;
jac=data->jac;
(*(data->jacf))(pext, jac, m, n, data->adata);
for(i=0; i<n; ++i){
jacextimm=jacext+i*mm;
jacim=jac+i*m;
for(j=0; j<m; ++j)
jacextimm[j]=jacim[j]; //jacext[i*mm+j]=jac[i*m+j];
for(j=m; j<mm; ++j)
jacextimm[j]=0.0; //jacext[i*mm+j]=0.0;
}
}
/*
* This function is similar to LEVMAR_DER except that the minimization is
* performed subject to the box constraints lb[i]<=p[i]<=ub[i], the linear
* equation constraints A*p=b, A being k1xm, b k1x1, and the linear inequality
* constraints C*p>=d, C being k2xm, d k2x1.
*
* The inequalities are converted to equations by introducing surplus variables,
* i.e. c^T*p >= d becomes c^T*p - y = d, with y>=0. To transform all inequalities
* to equations, a total of k2 surplus variables are introduced; a problem with only
* box and linear constraints results then and is solved with LEVMAR_BLEC_DER()
* Note that opposite direction inequalities should be converted to the desired
* direction by negating, i.e. c^T*p <= d becomes -c^T*p >= -d
*
* This function requires an analytic Jacobian. In case the latter is unavailable,
* use LEVMAR_BLEIC_DIF() bellow
*
*/
int LEVMAR_BLEIC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata), /* function to evaluate the Jacobian \part x / \part p */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *lb, /* I: vector of lower bounds. If NULL, no lower bounds apply */
LM_REAL *ub, /* I: vector of upper bounds. If NULL, no upper bounds apply */
LM_REAL *A, /* I: equality constraints matrix, k1xm. If NULL, no linear equation constraints apply */
LM_REAL *b, /* I: right hand constraints vector, k1x1 */
int k1, /* I: number of constraints (i.e. A's #rows) */
LM_REAL *C, /* I: inequality constraints matrix, k2xm */
LM_REAL *d, /* I: right hand constraints vector, k2x1 */
int k2, /* I: number of inequality constraints (i.e. C's #rows) */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[4], /* I: minim. options [\mu, \epsilon1, \epsilon2, \epsilon3]. Respectively the scale factor for initial \mu,
* stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2. Set to NULL for defaults to be used
*/
LM_REAL info[LM_INFO_SZ],
/* O: information regarding the minimization. Set to NULL if don't care
* info[0]= ||e||_2 at initial p.
* info[1-4]=[ ||e||_2, ||J^T e||_inf, ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
* info[5]= # iterations,
* info[6]=reason for terminating: 1 - stopped by small gradient J^T e
* 2 - stopped by small Dp
* 3 - stopped by itmax
* 4 - singular matrix. Restart from current p with increased mu
* 5 - no further error reduction is possible. Restart with increased mu
* 6 - stopped by small ||e||_2
* 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
* info[7]= # function evaluations
* info[8]= # Jacobian evaluations
* info[9]= # linear systems solved, i.e. # attempts for reducing error
*/
LM_REAL *work, /* working memory at least LM_BLEIC_DER_WORKSZ() reals large, allocated if NULL */
LM_REAL *covar, /* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
void *adata) /* pointer to possibly additional data, passed uninterpreted to func & jacf.
* Set to NULL if not needed
*/
{
struct LMBLEIC_DATA data;
LM_REAL *ptr, *pext, *Aext, *bext, *covext; /* corresponding to p, A, b, covar for the full set of variables;
pext=[p, surplus], pext is mm, Aext is (k1+k2)xmm, bext (k1+k2), covext is mmxmm
*/
LM_REAL *lbext, *ubext; // corresponding to lb, ub for the full set of variables
int mm, ret, k12;
register int i, j, ii;
register LM_REAL tmp;
LM_REAL locinfo[LM_INFO_SZ];
if(!jacf){
fprintf(stderr, RCAT("No function specified for computing the Jacobian in ", LEVMAR_BLEIC_DER)
RCAT("().\nIf no such function is available, use ", LEVMAR_BLEIC_DIF) RCAT("() rather than ", LEVMAR_BLEIC_DER) "()\n");
return LM_ERROR;
}
if(!C || !d){
fprintf(stderr, RCAT(LCAT(LEVMAR_BLEIC_DER, "(): missing inequality constraints, use "), LEVMAR_BLEC_DER) "() in this case!\n");
return LM_ERROR;
}
if(!A || !b) k1=0; // sanity check
mm=m+k2;
if(n<m-k1){
fprintf(stderr, LCAT(LEVMAR_BLEIC_DER, "(): cannot solve a problem with fewer measurements + equality constraints [%d + %d] than unknowns [%d]\n"), n, k1, m);
return LM_ERROR;
}
k12=k1+k2;
ptr=(LM_REAL *)malloc((3*mm + k12*mm + k12 + n*m + (covar? mm*mm : 0))*sizeof(LM_REAL));
if(!ptr){
fprintf(stderr, LCAT(LEVMAR_BLEIC_DER, "(): memory allocation request failed\n"));
return LM_ERROR;
}
pext=ptr;
lbext=pext+mm;
ubext=lbext+mm;
Aext=ubext+mm;
bext=Aext+k12*mm;
data.jac=bext+k12;
covext=covar? data.jac+n*m : NULL;
data.nineqcnstr=k2;
data.func=func;
data.jacf=jacf;
data.adata=adata;
/* compute y s.t. C*p - y=d, i.e. y=C*p-d.
* y is stored in the last k2 elements of pext
*/
for(i=0; i<k2; ++i){
for(j=0, tmp=0.0; j<m; ++j)
tmp+=C[i*m+j]*p[j];
pext[j=i+m]=tmp-d[i];
/* surplus variables must be >=0 */
lbext[j]=0.0;
ubext[j]=LM_REAL_MAX;
}
/* set the first m elements of pext equal to p */
for(i=0; i<m; ++i){
pext[i]=p[i];
lbext[i]=lb? lb[i] : LM_REAL_MIN;
ubext[i]=ub? ub[i] : LM_REAL_MAX;
}
/* setup the constraints matrix */
/* original linear equation constraints */
for(i=0; i<k1; ++i){
for(j=0; j<m; ++j)
Aext[i*mm+j]=A[i*m+j];
for(j=m; j<mm; ++j)
Aext[i*mm+j]=0.0;
bext[i]=b[i];
}
/* linear equation constraints resulting from surplus variables */
for(i=0, ii=k1; i<k2; ++i, ++ii){
for(j=0; j<m; ++j)
Aext[ii*mm+j]=C[i*m+j];
for(j=m; j<mm; ++j)
Aext[ii*mm+j]=0.0;
Aext[ii*mm+m+i]=-1.0;
bext[ii]=d[i];
}
if(!info) info=locinfo; /* make sure that LEVMAR_BLEC_DER() is called with non-null info */
/* note that the default weights for the penalty terms are being used below */
ret=LEVMAR_BLEC_DER(LMBLEIC_FUNC, LMBLEIC_JACF, pext, x, mm, n, lbext, ubext, Aext, bext, k12, NULL, itmax, opts, info, work, covext, (void *)&data);
/* copy back the minimizer */
for(i=0; i<m; ++i)
p[i]=pext[i];
#if 0
printf("Surplus variables for the minimizer:\n");
for(i=m; i<mm; ++i)
printf("%g ", pext[i]);
printf("\n\n");
#endif
if(covar){
for(i=0; i<m; ++i){
for(j=0; j<m; ++j)
covar[i*m+j]=covext[i*mm+j];
}
}
free(ptr);
return ret;
}
/* Similar to the LEVMAR_BLEIC_DER() function above, except that the Jacobian is approximated
* with the aid of finite differences (forward or central, see the comment for the opts argument)
*/
int LEVMAR_BLEIC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *lb, /* I: vector of lower bounds. If NULL, no lower bounds apply */
LM_REAL *ub, /* I: vector of upper bounds. If NULL, no upper bounds apply */
LM_REAL *A, /* I: equality constraints matrix, k1xm. If NULL, no linear equation constraints apply */
LM_REAL *b, /* I: right hand constraints vector, k1x1 */
int k1, /* I: number of constraints (i.e. A's #rows) */
LM_REAL *C, /* I: inequality constraints matrix, k2xm */
LM_REAL *d, /* I: right hand constraints vector, k2x1 */
int k2, /* I: number of inequality constraints (i.e. C's #rows) */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[5], /* I: opts[0-3] = minim. options [\mu, \epsilon1, \epsilon2, \epsilon3, \delta]. Respectively the
* scale factor for initial \mu, stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2 and
* the step used in difference approximation to the Jacobian. Set to NULL for defaults to be used.
* If \delta<0, the Jacobian is approximated with central differences which are more accurate
* (but slower!) compared to the forward differences employed by default.
*/
LM_REAL info[LM_INFO_SZ],
/* O: information regarding the minimization. Set to NULL if don't care
* info[0]= ||e||_2 at initial p.
* info[1-4]=[ ||e||_2, ||J^T e||_inf, ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
* info[5]= # iterations,
* info[6]=reason for terminating: 1 - stopped by small gradient J^T e
* 2 - stopped by small Dp
* 3 - stopped by itmax
* 4 - singular matrix. Restart from current p with increased mu
* 5 - no further error reduction is possible. Restart with increased mu
* 6 - stopped by small ||e||_2
* 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
* info[7]= # function evaluations
* info[8]= # Jacobian evaluations
* info[9]= # linear systems solved, i.e. # attempts for reducing error
*/
LM_REAL *work, /* working memory at least LM_BLEIC_DIF_WORKSZ() reals large, allocated if NULL */
LM_REAL *covar, /* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
void *adata) /* pointer to possibly additional data, passed uninterpreted to func.
* Set to NULL if not needed
*/
{
struct LMBLEIC_DATA data;
LM_REAL *ptr, *pext, *Aext, *bext, *covext; /* corresponding to p, A, b, covar for the full set of variables;
pext=[p, surplus], pext is mm, Aext is (k1+k2)xmm, bext (k1+k2), covext is mmxmm
*/
LM_REAL *lbext, *ubext; // corresponding to lb, ub for the full set of variables
int mm, ret, k12;
register int i, j, ii;
register LM_REAL tmp;
LM_REAL locinfo[LM_INFO_SZ];
if(!C || !d){
fprintf(stderr, RCAT(LCAT(LEVMAR_BLEIC_DIF, "(): missing inequality constraints, use "), LEVMAR_BLEC_DIF) "() in this case!\n");
return LM_ERROR;
}
if(!A || !b) k1=0; // sanity check
mm=m+k2;
if(n<m-k1){
fprintf(stderr, LCAT(LEVMAR_BLEIC_DIF, "(): cannot solve a problem with fewer measurements + equality constraints [%d + %d] than unknowns [%d]\n"), n, k1, m);
return LM_ERROR;
}
k12=k1+k2;
ptr=(LM_REAL *)malloc((3*mm + k12*mm + k12 + (covar? mm*mm : 0))*sizeof(LM_REAL));
if(!ptr){
fprintf(stderr, LCAT(LEVMAR_BLEIC_DIF, "(): memory allocation request failed\n"));
return LM_ERROR;
}
pext=ptr;
lbext=pext+mm;
ubext=lbext+mm;
Aext=ubext+mm;
bext=Aext+k12*mm;
data.jac=NULL;
covext=covar? bext+k12 : NULL;
data.nineqcnstr=k2;
data.func=func;
data.jacf=NULL;
data.adata=adata;
/* compute y s.t. C*p - y=d, i.e. y=C*p-d.
* y is stored in the last k2 elements of pext
*/
for(i=0; i<k2; ++i){
for(j=0, tmp=0.0; j<m; ++j)
tmp+=C[i*m+j]*p[j];
pext[j=i+m]=tmp-d[i];
/* surplus variables must be >=0 */
lbext[j]=0.0;
ubext[j]=LM_REAL_MAX;
}
/* set the first m elements of pext equal to p */
for(i=0; i<m; ++i){
pext[i]=p[i];
lbext[i]=lb? lb[i] : LM_REAL_MIN;
ubext[i]=ub? ub[i] : LM_REAL_MAX;
}
/* setup the constraints matrix */
/* original linear equation constraints */
for(i=0; i<k1; ++i){
for(j=0; j<m; ++j)
Aext[i*mm+j]=A[i*m+j];
for(j=m; j<mm; ++j)
Aext[i*mm+j]=0.0;
bext[i]=b[i];
}
/* linear equation constraints resulting from surplus variables */
for(i=0, ii=k1; i<k2; ++i, ++ii){
for(j=0; j<m; ++j)
Aext[ii*mm+j]=C[i*m+j];
for(j=m; j<mm; ++j)
Aext[ii*mm+j]=0.0;
Aext[ii*mm+m+i]=-1.0;
bext[ii]=d[i];
}
if(!info) info=locinfo; /* make sure that LEVMAR_BLEC_DIF() is called with non-null info */
/* note that the default weights for the penalty terms are being used below */
ret=LEVMAR_BLEC_DIF(LMBLEIC_FUNC, pext, x, mm, n, lbext, ubext, Aext, bext, k12, NULL, itmax, opts, info, work, covext, (void *)&data);
/* copy back the minimizer */
for(i=0; i<m; ++i)
p[i]=pext[i];
#if 0
printf("Surplus variables for the minimizer:\n");
for(i=m; i<mm; ++i)
printf("%g ", pext[i]);
printf("\n\n");
#endif
if(covar){
for(i=0; i<m; ++i){
for(j=0; j<m; ++j)
covar[i*m+j]=covext[i*mm+j];
}
}
free(ptr);
return ret;
}
/* convenience wrappers to LEVMAR_BLEIC_DER/LEVMAR_BLEIC_DIF */
/* box & linear inequality constraints */
int LEVMAR_BLIC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *lb, LM_REAL *ub,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[4], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DER(func, jacf, p, x, m, n, lb, ub, NULL, NULL, 0, C, d, k2, itmax, opts, info, work, covar, adata);
}
int LEVMAR_BLIC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *lb, LM_REAL *ub,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[5], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DIF(func, p, x, m, n, lb, ub, NULL, NULL, 0, C, d, k2, itmax, opts, info, work, covar, adata);
}
/* linear equation & inequality constraints */
int LEVMAR_LEIC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *A, LM_REAL *b, int k1,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[4], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DER(func, jacf, p, x, m, n, NULL, NULL, A, b, k1, C, d, k2, itmax, opts, info, work, covar, adata);
}
int LEVMAR_LEIC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *A, LM_REAL *b, int k1,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[5], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DIF(func, p, x, m, n, NULL, NULL, A, b, k1, C, d, k2, itmax, opts, info, work, covar, adata);
}
/* linear inequality constraints */
int LEVMAR_LIC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[4], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DER(func, jacf, p, x, m, n, NULL, NULL, NULL, NULL, 0, C, d, k2, itmax, opts, info, work, covar, adata);
}
int LEVMAR_LIC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n,
LM_REAL *C, LM_REAL *d, int k2,
int itmax, LM_REAL opts[5], LM_REAL info[LM_INFO_SZ], LM_REAL *work, LM_REAL *covar, void *adata)
{
return LEVMAR_BLEIC_DIF(func, p, x, m, n, NULL, NULL, NULL, NULL, 0, C, d, k2, itmax, opts, info, work, covar, adata);
}
/* undefine all. THIS MUST REMAIN AT THE END OF THE FILE */
#undef LMBLEIC_DATA
#undef LMBLEIC_ELIM
#undef LMBLEIC_FUNC
#undef LMBLEIC_JACF
#undef LEVMAR_FDIF_FORW_JAC_APPROX
#undef LEVMAR_COVAR
#undef LEVMAR_TRANS_MAT_MAT_MULT
#undef LEVMAR_BLEIC_DER
#undef LEVMAR_BLEIC_DIF
#undef LEVMAR_BLIC_DER
#undef LEVMAR_BLIC_DIF
#undef LEVMAR_LEIC_DER
#undef LEVMAR_LEIC_DIF
#undef LEVMAR_LIC_DER
#undef LEVMAR_LIC_DIF
#undef LEVMAR_BLEC_DER
#undef LEVMAR_BLEC_DIF

View File

@@ -1,80 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-05 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
* Wrappers for linearly constrained Levenberg-Marquardt minimization. The same
* core code is used with appropriate #defines to derive single and double
* precision versions, see also lmlec_core.c
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "levmar.h"
#include "misc.h"
#ifndef HAVE_LAPACK
#ifdef _MSC_VER
#pragma message("Linearly constrained optimization requires LAPACK and was not compiled!")
#else
#warning Linearly constrained optimization requires LAPACK and was not compiled!
#endif // _MSC_VER
#else // LAPACK present
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "lmlec_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_CNST(x) (x)
#include "lmlec_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_CNST
#endif /* LM_DBL_PREC */
#endif /* HAVE_LAPACK */

View File

@@ -1,656 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-05 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef LM_REAL // not included by lmlec.c
#error This file should not be compiled directly!
#endif
/* precision-specific definitions */
#define LMLEC_DATA LM_ADD_PREFIX(lmlec_data)
#define LMLEC_ELIM LM_ADD_PREFIX(lmlec_elim)
#define LMLEC_FUNC LM_ADD_PREFIX(lmlec_func)
#define LMLEC_JACF LM_ADD_PREFIX(lmlec_jacf)
#define LEVMAR_LEC_DER LM_ADD_PREFIX(levmar_lec_der)
#define LEVMAR_LEC_DIF LM_ADD_PREFIX(levmar_lec_dif)
#define LEVMAR_DER LM_ADD_PREFIX(levmar_der)
#define LEVMAR_DIF LM_ADD_PREFIX(levmar_dif)
#define LEVMAR_TRANS_MAT_MAT_MULT LM_ADD_PREFIX(levmar_trans_mat_mat_mult)
#define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)
#define LEVMAR_FDIF_FORW_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_forw_jac_approx)
#define GEQP3 LM_MK_LAPACK_NAME(geqp3)
#define ORGQR LM_MK_LAPACK_NAME(orgqr)
#define TRTRI LM_MK_LAPACK_NAME(trtri)
struct LMLEC_DATA{
LM_REAL *c, *Z, *p, *jac;
int ncnstr;
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata);
void (*jacf)(LM_REAL *p, LM_REAL *jac, int m, int n, void *adata);
void *adata;
};
/* prototypes for LAPACK routines */
#ifdef __cplusplus
extern "C" {
#endif
extern int GEQP3(int *m, int *n, LM_REAL *a, int *lda, int *jpvt,
LM_REAL *tau, LM_REAL *work, int *lwork, int *info);
extern int ORGQR(int *m, int *n, int *k, LM_REAL *a, int *lda, LM_REAL *tau,
LM_REAL *work, int *lwork, int *info);
extern int TRTRI(char *uplo, char *diag, int *n, LM_REAL *a, int *lda, int *info);
#ifdef __cplusplus
}
#endif
/*
* This function implements an elimination strategy for linearly constrained
* optimization problems. The strategy relies on QR decomposition to transform
* an optimization problem constrained by Ax=b to an equivalent, unconstrained
* one. Also referred to as "null space" or "reduced Hessian" method.
* See pp. 430-433 (chap. 15) of "Numerical Optimization" by Nocedal-Wright
* for details.
*
* A is mxn with m<=n and rank(A)=m
* Two matrices Y and Z of dimensions nxm and nx(n-m) are computed from A^T so that
* their columns are orthonormal and every x can be written as x=Y*b + Z*x_z=
* c + Z*x_z, where c=Y*b is a fixed vector of dimension n and x_z is an
* arbitrary vector of dimension n-m. Then, the problem of minimizing f(x)
* subject to Ax=b is equivalent to minimizing f(c + Z*x_z) with no constraints.
* The computed Y and Z are such that any solution of Ax=b can be written as
* x=Y*x_y + Z*x_z for some x_y, x_z. Furthermore, A*Y is nonsingular, A*Z=0
* and Z spans the null space of A.
*
* The function accepts A, b and computes c, Y, Z. If b or c is NULL, c is not
* computed. Also, Y can be NULL in which case it is not referenced.
* The function returns LM_ERROR in case of error, A's computed rank if successful
*
*/
static int LMLEC_ELIM(LM_REAL *A, LM_REAL *b, LM_REAL *c, LM_REAL *Y, LM_REAL *Z, int m, int n)
{
static LM_REAL eps=LM_CNST(-1.0);
LM_REAL *buf=NULL;
LM_REAL *a, *tau, *work, *r, aux;
register LM_REAL tmp;
int a_sz, jpvt_sz, tau_sz, r_sz, Y_sz, worksz;
int info, rank, *jpvt, tot_sz, mintmn, tm, tn;
register int i, j, k;
if(m>n){
fprintf(stderr, RCAT("matrix of constraints cannot have more rows than columns in", LMLEC_ELIM) "()!\n");
return LM_ERROR;
}
tm=n; tn=m; // transpose dimensions
mintmn=m;
/* calculate required memory size */
worksz=-1; // workspace query. Optimal work size is returned in aux
//ORGQR((int *)&tm, (int *)&tm, (int *)&mintmn, NULL, (int *)&tm, NULL, (LM_REAL *)&aux, &worksz, &info);
GEQP3((int *)&tm, (int *)&tn, NULL, (int *)&tm, NULL, NULL, (LM_REAL *)&aux, (int *)&worksz, &info);
worksz=(int)aux;
a_sz=tm*tm; // tm*tn is enough for xgeqp3()
jpvt_sz=tn;
tau_sz=mintmn;
r_sz=mintmn*mintmn; // actually smaller if a is not of full row rank
Y_sz=(Y)? 0 : tm*tn;
tot_sz=(a_sz + tau_sz + r_sz + worksz + Y_sz)*sizeof(LM_REAL) + jpvt_sz*sizeof(int); /* should be arranged in that order for proper doubles alignment */
buf=(LM_REAL *)malloc(tot_sz); /* allocate a "big" memory chunk at once */
if(!buf){
fprintf(stderr, RCAT("Memory allocation request failed in ", LMLEC_ELIM) "()\n");
return LM_ERROR;
}
a=buf;
tau=a+a_sz;
r=tau+tau_sz;
work=r+r_sz;
if(!Y){
Y=work+worksz;
jpvt=(int *)(Y+Y_sz);
}
else
jpvt=(int *)(work+worksz);
/* copy input array so that LAPACK won't destroy it. Note that copying is
* done in row-major order, which equals A^T in column-major
*/
for(i=0; i<tm*tn; ++i)
a[i]=A[i];
/* clear jpvt */
for(i=0; i<jpvt_sz; ++i) jpvt[i]=0;
/* rank revealing QR decomposition of A^T*/
GEQP3((int *)&tm, (int *)&tn, a, (int *)&tm, jpvt, tau, work, (int *)&worksz, &info);
//dgeqpf_((int *)&tm, (int *)&tn, a, (int *)&tm, jpvt, tau, work, &info);
/* error checking */
if(info!=0){
if(info<0){
fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", GEQP3) " in ", LMLEC_ELIM) "()\n", -info);
}
else if(info>0){
fprintf(stderr, RCAT(RCAT("unknown LAPACK error (%d) for ", GEQP3) " in ", LMLEC_ELIM) "()\n", info);
}
free(buf);
return LM_ERROR;
}
/* the upper triangular part of a now contains the upper triangle of the unpermuted R */
if(eps<0.0){
LM_REAL aux;
/* compute machine epsilon. DBL_EPSILON should do also */
for(eps=LM_CNST(1.0); aux=eps+LM_CNST(1.0), aux-LM_CNST(1.0)>0.0; eps*=LM_CNST(0.5))
;
eps*=LM_CNST(2.0);
}
tmp=tm*LM_CNST(10.0)*eps*FABS(a[0]); // threshold. tm is max(tm, tn)
tmp=(tmp>LM_CNST(1E-12))? tmp : LM_CNST(1E-12); // ensure that threshold is not too small
/* compute A^T's numerical rank by counting the non-zeros in R's diagonal */
for(i=rank=0; i<mintmn; ++i)
if(a[i*(tm+1)]>tmp || a[i*(tm+1)]<-tmp) ++rank; /* loop across R's diagonal elements */
else break; /* diagonal is arranged in absolute decreasing order */
if(rank<tn){
fprintf(stderr, RCAT("\nConstraints matrix in ", LMLEC_ELIM) "() is not of full row rank (i.e. %d < %d)!\n"
"Make sure that you do not specify redundant or inconsistent constraints.\n\n", rank, tn);
free(buf);
return LM_ERROR;
}
/* compute the permuted inverse transpose of R */
/* first, copy R from the upper triangular part of a to the lower part of r (thus transposing it). R is rank x rank */
for(j=0; j<rank; ++j){
for(i=0; i<=j; ++i)
r[j+i*rank]=a[i+j*tm];
for(i=j+1; i<rank; ++i)
r[j+i*rank]=0.0; // upper part is zero
}
/* r now contains R^T */
/* compute the inverse */
TRTRI("L", "N", (int *)&rank, r, (int *)&rank, &info);
/* error checking */
if(info!=0){
if(info<0){
fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", TRTRI) " in ", LMLEC_ELIM) "()\n", -info);
}
else if(info>0){
fprintf(stderr, RCAT(RCAT("A(%d, %d) is exactly zero for ", TRTRI) " (singular matrix) in ", LMLEC_ELIM) "()\n", info, info);
}
free(buf);
return LM_ERROR;
}
/* finally, permute R^-T using Y as intermediate storage */
for(j=0; j<rank; ++j)
for(i=0, k=jpvt[j]-1; i<rank; ++i)
Y[i+k*rank]=r[i+j*rank];
for(i=0; i<rank*rank; ++i) // copy back to r
r[i]=Y[i];
/* resize a to be tm x tm, filling with zeroes */
for(i=tm*tn; i<tm*tm; ++i)
a[i]=0.0;
/* compute Q in a as the product of elementary reflectors. Q is tm x tm */
ORGQR((int *)&tm, (int *)&tm, (int *)&mintmn, a, (int *)&tm, tau, work, &worksz, &info);
/* error checking */
if(info!=0){
if(info<0){
fprintf(stderr, RCAT(RCAT("LAPACK error: illegal value for argument %d of ", ORGQR) " in ", LMLEC_ELIM) "()\n", -info);
}
else if(info>0){
fprintf(stderr, RCAT(RCAT("unknown LAPACK error (%d) for ", ORGQR) " in ", LMLEC_ELIM) "()\n", info);
}
free(buf);
return LM_ERROR;
}
/* compute Y=Q_1*R^-T*P^T. Y is tm x rank */
for(i=0; i<tm; ++i)
for(j=0; j<rank; ++j){
for(k=0, tmp=0.0; k<rank; ++k)
tmp+=a[i+k*tm]*r[k+j*rank];
Y[i*rank+j]=tmp;
}
if(b && c){
/* compute c=Y*b */
for(i=0; i<tm; ++i){
for(j=0, tmp=0.0; j<rank; ++j)
tmp+=Y[i*rank+j]*b[j];
c[i]=tmp;
}
}
/* copy Q_2 into Z. Z is tm x (tm-rank) */
for(j=0; j<tm-rank; ++j)
for(i=0, k=j+rank; i<tm; ++i)
Z[i*(tm-rank)+j]=a[i+k*tm];
free(buf);
return rank;
}
/* constrained measurements: given pp, compute the measurements at c + Z*pp */
static void LMLEC_FUNC(LM_REAL *pp, LM_REAL *hx, int mm, int n, void *adata)
{
struct LMLEC_DATA *data=(struct LMLEC_DATA *)adata;
int m;
register int i, j;
register LM_REAL sum;
LM_REAL *c, *Z, *p, *Zimm;
m=mm+data->ncnstr;
c=data->c;
Z=data->Z;
p=data->p;
/* p=c + Z*pp */
for(i=0; i<m; ++i){
Zimm=Z+i*mm;
for(j=0, sum=c[i]; j<mm; ++j)
sum+=Zimm[j]*pp[j]; // sum+=Z[i*mm+j]*pp[j];
p[i]=sum;
}
(*(data->func))(p, hx, m, n, data->adata);
}
/* constrained Jacobian: given pp, compute the Jacobian at c + Z*pp
* Using the chain rule, the Jacobian with respect to pp equals the
* product of the Jacobian with respect to p (at c + Z*pp) times Z
*/
static void LMLEC_JACF(LM_REAL *pp, LM_REAL *jacjac, int mm, int n, void *adata)
{
struct LMLEC_DATA *data=(struct LMLEC_DATA *)adata;
int m;
register int i, j, l;
register LM_REAL sum, *aux1, *aux2;
LM_REAL *c, *Z, *p, *jac;
m=mm+data->ncnstr;
c=data->c;
Z=data->Z;
p=data->p;
jac=data->jac;
/* p=c + Z*pp */
for(i=0; i<m; ++i){
aux1=Z+i*mm;
for(j=0, sum=c[i]; j<mm; ++j)
sum+=aux1[j]*pp[j]; // sum+=Z[i*mm+j]*pp[j];
p[i]=sum;
}
(*(data->jacf))(p, jac, m, n, data->adata);
/* compute jac*Z in jacjac */
if(n*m<=__BLOCKSZ__SQ){ // this is a small problem
/* This is the straightforward way to compute jac*Z. However, due to
* its noncontinuous memory access pattern, it incures many cache misses when
* applied to large minimization problems (i.e. problems involving a large
* number of free variables and measurements), in which jac is too large to
* fit in the L1 cache. For such problems, a cache-efficient blocking scheme
* is preferable. On the other hand, the straightforward algorithm is faster
* on small problems since in this case it avoids the overheads of blocking.
*/
for(i=0; i<n; ++i){
aux1=jac+i*m;
aux2=jacjac+i*mm;
for(j=0; j<mm; ++j){
for(l=0, sum=0.0; l<m; ++l)
sum+=aux1[l]*Z[l*mm+j]; // sum+=jac[i*m+l]*Z[l*mm+j];
aux2[j]=sum; // jacjac[i*mm+j]=sum;
}
}
}
else{ // this is a large problem
/* Cache efficient computation of jac*Z based on blocking
*/
#define __MIN__(x, y) (((x)<=(y))? (x) : (y))
register int jj, ll;
for(jj=0; jj<mm; jj+=__BLOCKSZ__){
for(i=0; i<n; ++i){
aux1=jacjac+i*mm;
for(j=jj; j<__MIN__(jj+__BLOCKSZ__, mm); ++j)
aux1[j]=0.0; //jacjac[i*mm+j]=0.0;
}
for(ll=0; ll<m; ll+=__BLOCKSZ__){
for(i=0; i<n; ++i){
aux1=jacjac+i*mm; aux2=jac+i*m;
for(j=jj; j<__MIN__(jj+__BLOCKSZ__, mm); ++j){
sum=0.0;
for(l=ll; l<__MIN__(ll+__BLOCKSZ__, m); ++l)
sum+=aux2[l]*Z[l*mm+j]; //jac[i*m+l]*Z[l*mm+j];
aux1[j]+=sum; //jacjac[i*mm+j]+=sum;
}
}
}
}
}
}
#undef __MIN__
/*
* This function is similar to LEVMAR_DER except that the minimization
* is performed subject to the linear constraints A p=b, A is kxm, b kx1
*
* This function requires an analytic Jacobian. In case the latter is unavailable,
* use LEVMAR_LEC_DIF() bellow
*
*/
int LEVMAR_LEC_DER(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata), /* function to evaluate the Jacobian \part x / \part p */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *A, /* I: constraints matrix, kxm */
LM_REAL *b, /* I: right hand constraints vector, kx1 */
int k, /* I: number of constraints (i.e. A's #rows) */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[4], /* I: minim. options [\mu, \epsilon1, \epsilon2, \epsilon3]. Respectively the scale factor for initial \mu,
* stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2. Set to NULL for defaults to be used
*/
LM_REAL info[LM_INFO_SZ],
/* O: information regarding the minimization. Set to NULL if don't care
* info[0]= ||e||_2 at initial p.
* info[1-4]=[ ||e||_2, ||J^T e||_inf, ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
* info[5]= # iterations,
* info[6]=reason for terminating: 1 - stopped by small gradient J^T e
* 2 - stopped by small Dp
* 3 - stopped by itmax
* 4 - singular matrix. Restart from current p with increased mu
* 5 - no further error reduction is possible. Restart with increased mu
* 6 - stopped by small ||e||_2
* 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
* info[7]= # function evaluations
* info[8]= # Jacobian evaluations
* info[9]= # linear systems solved, i.e. # attempts for reducing error
*/
LM_REAL *work, /* working memory at least LM_LEC_DER_WORKSZ() reals large, allocated if NULL */
LM_REAL *covar, /* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
void *adata) /* pointer to possibly additional data, passed uninterpreted to func & jacf.
* Set to NULL if not needed
*/
{
struct LMLEC_DATA data;
LM_REAL *ptr, *Z, *pp, *p0, *Zimm; /* Z is mxmm */
int mm, ret;
register int i, j;
register LM_REAL tmp;
LM_REAL locinfo[LM_INFO_SZ];
if(!jacf){
fprintf(stderr, RCAT("No function specified for computing the Jacobian in ", LEVMAR_LEC_DER)
RCAT("().\nIf no such function is available, use ", LEVMAR_LEC_DIF) RCAT("() rather than ", LEVMAR_LEC_DER) "()\n");
return LM_ERROR;
}
mm=m-k;
if(n<mm){
fprintf(stderr, LCAT(LEVMAR_LEC_DER, "(): cannot solve a problem with fewer measurements + equality constraints [%d + %d] than unknowns [%d]\n"), n, k, m);
return LM_ERROR;
}
ptr=(LM_REAL *)malloc((2*m + m*mm + n*m + mm)*sizeof(LM_REAL));
if(!ptr){
fprintf(stderr, LCAT(LEVMAR_LEC_DER, "(): memory allocation request failed\n"));
return LM_ERROR;
}
data.p=p;
p0=ptr;
data.c=p0+m;
data.Z=Z=data.c+m;
data.jac=data.Z+m*mm;
pp=data.jac+n*m;
data.ncnstr=k;
data.func=func;
data.jacf=jacf;
data.adata=adata;
ret=LMLEC_ELIM(A, b, data.c, NULL, Z, k, m); // compute c, Z
if(ret==LM_ERROR){
free(ptr);
return LM_ERROR;
}
/* compute pp s.t. p = c + Z*pp or (Z^T Z)*pp=Z^T*(p-c)
* Due to orthogonality, Z^T Z = I and the last equation
* becomes pp=Z^T*(p-c). Also, save the starting p in p0
*/
for(i=0; i<m; ++i){
p0[i]=p[i];
p[i]-=data.c[i];
}
/* Z^T*(p-c) */
for(i=0; i<mm; ++i){
for(j=0, tmp=0.0; j<m; ++j)
tmp+=Z[j*mm+i]*p[j];
pp[i]=tmp;
}
/* compute the p corresponding to pp (i.e. c + Z*pp) and compare with p0 */
for(i=0; i<m; ++i){
Zimm=Z+i*mm;
for(j=0, tmp=data.c[i]; j<mm; ++j)
tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
if(FABS(tmp-p0[i])>LM_CNST(1E-03))
fprintf(stderr, RCAT("Warning: component %d of starting point not feasible in ", LEVMAR_LEC_DER) "()! [%.10g reset to %.10g]\n",
i, p0[i], tmp);
}
if(!info) info=locinfo; /* make sure that LEVMAR_DER() is called with non-null info */
/* note that covariance computation is not requested from LEVMAR_DER() */
ret=LEVMAR_DER(LMLEC_FUNC, LMLEC_JACF, pp, x, mm, n, itmax, opts, info, work, NULL, (void *)&data);
/* p=c + Z*pp */
for(i=0; i<m; ++i){
Zimm=Z+i*mm;
for(j=0, tmp=data.c[i]; j<mm; ++j)
tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
p[i]=tmp;
}
/* compute the covariance from the Jacobian in data.jac */
if(covar){
LEVMAR_TRANS_MAT_MAT_MULT(data.jac, covar, n, m); /* covar = J^T J */
LEVMAR_COVAR(covar, covar, info[1], m, n);
}
free(ptr);
return ret;
}
/* Similar to the LEVMAR_LEC_DER() function above, except that the Jacobian is approximated
* with the aid of finite differences (forward or central, see the comment for the opts argument)
*/
int LEVMAR_LEC_DIF(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata), /* functional relation describing measurements. A p \in R^m yields a \hat{x} \in R^n */
LM_REAL *p, /* I/O: initial parameter estimates. On output has the estimated solution */
LM_REAL *x, /* I: measurement vector. NULL implies a zero vector */
int m, /* I: parameter vector dimension (i.e. #unknowns) */
int n, /* I: measurement vector dimension */
LM_REAL *A, /* I: constraints matrix, kxm */
LM_REAL *b, /* I: right hand constraints vector, kx1 */
int k, /* I: number of constraints (i.e. A's #rows) */
int itmax, /* I: maximum number of iterations */
LM_REAL opts[5], /* I: opts[0-3] = minim. options [\mu, \epsilon1, \epsilon2, \epsilon3, \delta]. Respectively the
* scale factor for initial \mu, stopping thresholds for ||J^T e||_inf, ||Dp||_2 and ||e||_2 and
* the step used in difference approximation to the Jacobian. Set to NULL for defaults to be used.
* If \delta<0, the Jacobian is approximated with central differences which are more accurate
* (but slower!) compared to the forward differences employed by default.
*/
LM_REAL info[LM_INFO_SZ],
/* O: information regarding the minimization. Set to NULL if don't care
* info[0]= ||e||_2 at initial p.
* info[1-4]=[ ||e||_2, ||J^T e||_inf, ||Dp||_2, mu/max[J^T J]_ii ], all computed at estimated p.
* info[5]= # iterations,
* info[6]=reason for terminating: 1 - stopped by small gradient J^T e
* 2 - stopped by small Dp
* 3 - stopped by itmax
* 4 - singular matrix. Restart from current p with increased mu
* 5 - no further error reduction is possible. Restart with increased mu
* 6 - stopped by small ||e||_2
* 7 - stopped by invalid (i.e. NaN or Inf) "func" values. This is a user error
* info[7]= # function evaluations
* info[8]= # Jacobian evaluations
* info[9]= # linear systems solved, i.e. # attempts for reducing error
*/
LM_REAL *work, /* working memory at least LM_LEC_DIF_WORKSZ() reals large, allocated if NULL */
LM_REAL *covar, /* O: Covariance matrix corresponding to LS solution; mxm. Set to NULL if not needed. */
void *adata) /* pointer to possibly additional data, passed uninterpreted to func.
* Set to NULL if not needed
*/
{
struct LMLEC_DATA data;
LM_REAL *ptr, *Z, *pp, *p0, *Zimm; /* Z is mxmm */
int mm, ret;
register int i, j;
register LM_REAL tmp;
LM_REAL locinfo[LM_INFO_SZ];
mm=m-k;
if(n<mm){
fprintf(stderr, LCAT(LEVMAR_LEC_DIF, "(): cannot solve a problem with fewer measurements + equality constraints [%d + %d] than unknowns [%d]\n"), n, k, m);
return LM_ERROR;
}
ptr=(LM_REAL *)malloc((2*m + m*mm + mm)*sizeof(LM_REAL));
if(!ptr){
fprintf(stderr, LCAT(LEVMAR_LEC_DIF, "(): memory allocation request failed\n"));
return LM_ERROR;
}
data.p=p;
p0=ptr;
data.c=p0+m;
data.Z=Z=data.c+m;
data.jac=NULL;
pp=data.Z+m*mm;
data.ncnstr=k;
data.func=func;
data.jacf=NULL;
data.adata=adata;
ret=LMLEC_ELIM(A, b, data.c, NULL, Z, k, m); // compute c, Z
if(ret==LM_ERROR){
free(ptr);
return LM_ERROR;
}
/* compute pp s.t. p = c + Z*pp or (Z^T Z)*pp=Z^T*(p-c)
* Due to orthogonality, Z^T Z = I and the last equation
* becomes pp=Z^T*(p-c). Also, save the starting p in p0
*/
for(i=0; i<m; ++i){
p0[i]=p[i];
p[i]-=data.c[i];
}
/* Z^T*(p-c) */
for(i=0; i<mm; ++i){
for(j=0, tmp=0.0; j<m; ++j)
tmp+=Z[j*mm+i]*p[j];
pp[i]=tmp;
}
/* compute the p corresponding to pp (i.e. c + Z*pp) and compare with p0 */
for(i=0; i<m; ++i){
Zimm=Z+i*mm;
for(j=0, tmp=data.c[i]; j<mm; ++j)
tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
if(FABS(tmp-p0[i])>LM_CNST(1E-03))
fprintf(stderr, RCAT("Warning: component %d of starting point not feasible in ", LEVMAR_LEC_DIF) "()! [%.10g reset to %.10g]\n",
i, p0[i], tmp);
}
if(!info) info=locinfo; /* make sure that LEVMAR_DIF() is called with non-null info */
/* note that covariance computation is not requested from LEVMAR_DIF() */
ret=LEVMAR_DIF(LMLEC_FUNC, pp, x, mm, n, itmax, opts, info, work, NULL, (void *)&data);
/* p=c + Z*pp */
for(i=0; i<m; ++i){
Zimm=Z+i*mm;
for(j=0, tmp=data.c[i]; j<mm; ++j)
tmp+=Zimm[j]*pp[j]; // tmp+=Z[i*mm+j]*pp[j];
p[i]=tmp;
}
/* compute the Jacobian with finite differences and use it to estimate the covariance */
if(covar){
LM_REAL *hx, *wrk, *jac;
hx=(LM_REAL *)malloc((2*n+n*m)*sizeof(LM_REAL));
if(!hx){
fprintf(stderr, LCAT(LEVMAR_LEC_DIF, "(): memory allocation request failed\n"));
free(ptr);
return LM_ERROR;
}
wrk=hx+n;
jac=wrk+n;
(*func)(p, hx, m, n, adata); /* evaluate function at p */
LEVMAR_FDIF_FORW_JAC_APPROX(func, p, hx, wrk, (LM_REAL)LM_DIFF_DELTA, jac, m, n, adata); /* compute the Jacobian at p */
LEVMAR_TRANS_MAT_MAT_MULT(jac, covar, n, m); /* covar = J^T J */
LEVMAR_COVAR(covar, covar, info[1], m, n);
free(hx);
}
free(ptr);
return ret;
}
/* undefine all. THIS MUST REMAIN AT THE END OF THE FILE */
#undef LMLEC_DATA
#undef LMLEC_ELIM
#undef LMLEC_FUNC
#undef LMLEC_JACF
#undef LEVMAR_FDIF_FORW_JAC_APPROX
#undef LEVMAR_COVAR
#undef LEVMAR_TRANS_MAT_MAT_MULT
#undef LEVMAR_LEC_DER
#undef LEVMAR_LEC_DIF
#undef LEVMAR_DER
#undef LEVMAR_DIF
#undef GEQP3
#undef ORGQR
#undef TRTRI

View File

@@ -1,70 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-05 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
/********************************************************************************
* Miscelaneous functions for Levenberg-Marquardt nonlinear minimization. The
* same core code is used with appropriate #defines to derive single and double
* precision versions, see also misc_core.c
********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <float.h>
#include "levmar.h"
#include "misc.h"
#if !defined(LM_DBL_PREC) && !defined(LM_SNGL_PREC)
#error At least one of LM_DBL_PREC, LM_SNGL_PREC should be defined!
#endif
#ifdef LM_SNGL_PREC
/* single precision (float) definitions */
#define LM_REAL float
#define LM_PREFIX s
#define LM_REAL_EPSILON FLT_EPSILON
#define __SUBCNST(x) x##F
#define LM_CNST(x) __SUBCNST(x) // force substitution
#include "misc_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_EPSILON
#undef __SUBCNST
#undef LM_CNST
#endif /* LM_SNGL_PREC */
#ifdef LM_DBL_PREC
/* double precision definitions */
#define LM_REAL double
#define LM_PREFIX d
#define LM_REAL_EPSILON DBL_EPSILON
#define LM_CNST(x) (x)
#include "misc_core.c" // read in core code
#undef LM_REAL
#undef LM_PREFIX
#undef LM_REAL_EPSILON
#undef LM_CNST
#endif /* LM_DBL_PREC */

View File

@@ -1,114 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef _MISC_H_
#define _MISC_H_
/* common suffix for LAPACK subroutines. Define empty in case of no prefix. */
#define LM_LAPACK_SUFFIX _
//#define LM_LAPACK_SUFFIX // define empty
/* common prefix for BLAS subroutines. Leave undefined in case of no prefix.
* You might also need to modify LM_BLAS_PREFIX below
*/
/* f2c'd BLAS */
//#define LM_BLAS_PREFIX f2c_
/* C BLAS */
//#define LM_BLAS_PREFIX cblas_
/* common suffix for BLAS subroutines */
//#define LM_BLAS_SUFFIX // define empty if a f2c_ or cblas_ prefix was defined for LM_BLAS_PREFIX above
#define LM_BLAS_SUFFIX _ // use this in case of no BLAS prefix
#define LCAT_(a, b) #a b
#define LCAT(a, b) LCAT_(a, b) // force substitution
#define RCAT_(a, b) a #b
#define RCAT(a, b) RCAT_(a, b) // force substitution
#define LM_MK_LAPACK_NAME(s) LM_ADD_PREFIX(LM_CAT_(s, LM_LAPACK_SUFFIX))
#ifdef LM_BLAS_PREFIX
#define LM_MK_BLAS_NAME(s) LM_CAT_(LM_BLAS_PREFIX, LM_ADD_PREFIX(LM_CAT_(s, LM_BLAS_SUFFIX)))
#else
#define LM_MK_BLAS_NAME(s) LM_ADD_PREFIX(LM_CAT_(s, LM_BLAS_SUFFIX))
#endif
#define __BLOCKSZ__ 32 /* block size for cache-friendly matrix-matrix multiply. It should be
* such that __BLOCKSZ__^2*sizeof(LM_REAL) is smaller than the CPU (L1)
* data cache size. Notice that a value of 32 when LM_REAL=double assumes
* an 8Kb L1 data cache (32*32*8=8K). This is a concervative choice since
* newer Pentium 4s have a L1 data cache of size 16K, capable of holding
* up to 45x45 double blocks.
*/
#define __BLOCKSZ__SQ (__BLOCKSZ__)*(__BLOCKSZ__)
/* add a prefix in front of a token */
#define LM_CAT__(a, b) a ## b
#define LM_CAT_(a, b) LM_CAT__(a, b) // force substitution
#define LM_ADD_PREFIX(s) LM_CAT_(LM_PREFIX, s)
#define FABS(x) (((x)>=0.0)? (x) : -(x))
#ifdef __cplusplus
extern "C" {
#endif
/* blocking-based matrix multiply */
extern void slevmar_trans_mat_mat_mult(float *a, float *b, int n, int m);
extern void dlevmar_trans_mat_mat_mult(double *a, double *b, int n, int m);
/* forward finite differences */
extern void slevmar_fdif_forw_jac_approx(void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *hx, float *hxx, float delta,
float *jac, int m, int n, void *adata);
extern void dlevmar_fdif_forw_jac_approx(void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *hx, double *hxx, double delta,
double *jac, int m, int n, void *adata);
/* central finite differences */
extern void slevmar_fdif_cent_jac_approx(void (*func)(float *p, float *hx, int m, int n, void *adata),
float *p, float *hxm, float *hxp, float delta,
float *jac, int m, int n, void *adata);
extern void dlevmar_fdif_cent_jac_approx(void (*func)(double *p, double *hx, int m, int n, void *adata),
double *p, double *hxm, double *hxp, double delta,
double *jac, int m, int n, void *adata);
/* e=x-y and ||e|| */
extern float slevmar_L2nrmxmy(float *e, float *x, float *y, int n);
extern double dlevmar_L2nrmxmy(double *e, double *x, double *y, int n);
/* covariance of LS fit */
extern int slevmar_covar(float *JtJ, float *C, float sumsq, int m, int n);
extern int dlevmar_covar(double *JtJ, double *C, double sumsq, int m, int n);
/* box constraints consistency check */
extern int slevmar_box_check(float *lb, float *ub, int m);
extern int dlevmar_box_check(double *lb, double *ub, int m);
/* Cholesky */
extern int slevmar_chol(float *C, float *W, int m);
extern int dlevmar_chol(double *C, double *W, int m);
#ifdef __cplusplus
}
#endif
#endif /* _MISC_H_ */

View File

@@ -1,831 +0,0 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Levenberg - Marquardt non-linear minimization algorithm
// Copyright (C) 2004-05 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef LM_REAL // not included by misc.c
#error This file should not be compiled directly!
#endif
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#pragma GCC diagnostic ignored "-Wcpp"
#endif
/* precision-specific definitions */
#define LEVMAR_CHKJAC LM_ADD_PREFIX(levmar_chkjac)
#define LEVMAR_FDIF_FORW_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_forw_jac_approx)
#define LEVMAR_FDIF_CENT_JAC_APPROX LM_ADD_PREFIX(levmar_fdif_cent_jac_approx)
#define LEVMAR_TRANS_MAT_MAT_MULT LM_ADD_PREFIX(levmar_trans_mat_mat_mult)
#define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)
#define LEVMAR_STDDEV LM_ADD_PREFIX(levmar_stddev)
#define LEVMAR_CORCOEF LM_ADD_PREFIX(levmar_corcoef)
#define LEVMAR_R2 LM_ADD_PREFIX(levmar_R2)
#define LEVMAR_BOX_CHECK LM_ADD_PREFIX(levmar_box_check)
#define LEVMAR_L2NRMXMY LM_ADD_PREFIX(levmar_L2nrmxmy)
#ifdef HAVE_LAPACK
#define LEVMAR_PSEUDOINVERSE LM_ADD_PREFIX(levmar_pseudoinverse)
static int LEVMAR_PSEUDOINVERSE(LM_REAL *A, LM_REAL *B, int m);
#ifdef __cplusplus
extern "C" {
#endif
/* BLAS matrix multiplication, LAPACK SVD & Cholesky routines */
#define GEMM LM_MK_BLAS_NAME(gemm)
/* C := alpha*op( A )*op( B ) + beta*C */
extern void GEMM(char *transa, char *transb, int *m, int *n, int *k,
LM_REAL *alpha, LM_REAL *a, int *lda, LM_REAL *b, int *ldb, LM_REAL *beta, LM_REAL *c, int *ldc);
#define GESVD LM_MK_LAPACK_NAME(gesvd)
#define GESDD LM_MK_LAPACK_NAME(gesdd)
extern int GESVD(char *jobu, char *jobvt, int *m, int *n, LM_REAL *a, int *lda, LM_REAL *s, LM_REAL *u, int *ldu,
LM_REAL *vt, int *ldvt, LM_REAL *work, int *lwork, int *info);
/* lapack 3.0 new SVD routine, faster than xgesvd() */
extern int GESDD(char *jobz, int *m, int *n, LM_REAL *a, int *lda, LM_REAL *s, LM_REAL *u, int *ldu, LM_REAL *vt, int *ldvt,
LM_REAL *work, int *lwork, int *iwork, int *info);
/* Cholesky decomposition */
#define POTF2 LM_MK_LAPACK_NAME(potf2)
extern int POTF2(char *uplo, int *n, LM_REAL *a, int *lda, int *info);
#ifdef __cplusplus
}
#endif
#define LEVMAR_CHOLESKY LM_ADD_PREFIX(levmar_chol)
#else /* !HAVE_LAPACK */
#define LEVMAR_LUINVERSE LM_ADD_PREFIX(levmar_LUinverse_noLapack)
static int LEVMAR_LUINVERSE(LM_REAL *A, LM_REAL *B, int m);
#endif /* HAVE_LAPACK */
/* blocked multiplication of the transpose of the nxm matrix a with itself (i.e. a^T a)
* using a block size of bsize. The product is returned in b.
* Since a^T a is symmetric, its computation can be sped up by computing only its
* upper triangular part and copying it to the lower part.
*
* More details on blocking can be found at
* http://www-2.cs.cmu.edu/afs/cs/academic/class/15213-f02/www/R07/section_a/Recitation07-SectionA.pdf
*/
void LEVMAR_TRANS_MAT_MAT_MULT(LM_REAL *a, LM_REAL *b, int n, int m)
{
#ifdef HAVE_LAPACK /* use BLAS matrix multiply */
LM_REAL alpha=LM_CNST(1.0), beta=LM_CNST(0.0);
/* Fool BLAS to compute a^T*a avoiding transposing a: a is equivalent to a^T in column major,
* therefore BLAS computes a*a^T with a and a*a^T in column major, which is equivalent to
* computing a^T*a in row major!
*/
GEMM("N", "T", &m, &m, &n, &alpha, a, &m, a, &m, &beta, b, &m);
#else /* no LAPACK, use blocking-based multiply */
register int i, j, k, jj, kk;
register LM_REAL sum, *bim, *akm;
const int bsize=__BLOCKSZ__;
#define __MIN__(x, y) (((x)<=(y))? (x) : (y))
#define __MAX__(x, y) (((x)>=(y))? (x) : (y))
/* compute upper triangular part using blocking */
for(jj=0; jj<m; jj+=bsize){
for(i=0; i<m; ++i){
bim=b+i*m;
for(j=__MAX__(jj, i); j<__MIN__(jj+bsize, m); ++j)
bim[j]=0.0; //b[i*m+j]=0.0;
}
for(kk=0; kk<n; kk+=bsize){
for(i=0; i<m; ++i){
bim=b+i*m;
for(j=__MAX__(jj, i); j<__MIN__(jj+bsize, m); ++j){
sum=0.0;
for(k=kk; k<__MIN__(kk+bsize, n); ++k){
akm=a+k*m;
sum+=akm[i]*akm[j]; //a[k*m+i]*a[k*m+j];
}
bim[j]+=sum; //b[i*m+j]+=sum;
}
}
}
}
/* copy upper triangular part to the lower one */
for(i=0; i<m; ++i)
for(j=0; j<i; ++j)
b[i*m+j]=b[j*m+i];
#undef __MIN__
#undef __MAX__
#endif /* HAVE_LAPACK */
}
/* forward finite difference approximation to the Jacobian of func */
void LEVMAR_FDIF_FORW_JAC_APPROX(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
/* function to differentiate */
LM_REAL *p, /* I: current parameter estimate, mx1 */
LM_REAL *hx, /* I: func evaluated at p, i.e. hx=func(p), nx1 */
LM_REAL *hxx, /* W/O: work array for evaluating func(p+delta), nx1 */
LM_REAL delta, /* increment for computing the Jacobian */
LM_REAL *jac, /* O: array for storing approximated Jacobian, nxm */
int m,
int n,
void *adata)
{
register int i, j;
LM_REAL tmp;
register LM_REAL d;
for(j=0; j<m; ++j){
/* determine d=max(1E-04*|p[j]|, delta), see HZ */
d=LM_CNST(1E-04)*p[j]; // force evaluation
d=FABS(d);
if(d<delta)
d=delta;
tmp=p[j];
p[j]+=d;
(*func)(p, hxx, m, n, adata);
p[j]=tmp; /* restore */
d=LM_CNST(1.0)/d; /* invert so that divisions can be carried out faster as multiplications */
for(i=0; i<n; ++i){
jac[i*m+j]=(hxx[i]-hx[i])*d;
}
}
}
/* central finite difference approximation to the Jacobian of func */
void LEVMAR_FDIF_CENT_JAC_APPROX(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
/* function to differentiate */
LM_REAL *p, /* I: current parameter estimate, mx1 */
LM_REAL *hxm, /* W/O: work array for evaluating func(p-delta), nx1 */
LM_REAL *hxp, /* W/O: work array for evaluating func(p+delta), nx1 */
LM_REAL delta, /* increment for computing the Jacobian */
LM_REAL *jac, /* O: array for storing approximated Jacobian, nxm */
int m,
int n,
void *adata)
{
register int i, j;
LM_REAL tmp;
register LM_REAL d;
for(j=0; j<m; ++j){
/* determine d=max(1E-04*|p[j]|, delta), see HZ */
d=LM_CNST(1E-04)*p[j]; // force evaluation
d=FABS(d);
if(d<delta)
d=delta;
tmp=p[j];
p[j]-=d;
(*func)(p, hxm, m, n, adata);
p[j]=tmp+d;
(*func)(p, hxp, m, n, adata);
p[j]=tmp; /* restore */
d=LM_CNST(0.5)/d; /* invert so that divisions can be carried out faster as multiplications */
for(i=0; i<n; ++i){
jac[i*m+j]=(hxp[i]-hxm[i])*d;
}
}
}
/*
* Check the Jacobian of a n-valued nonlinear function in m variables
* evaluated at a point p, for consistency with the function itself.
*
* Based on fortran77 subroutine CHKDER by
* Burton S. Garbow, Kenneth E. Hillstrom, Jorge J. More
* Argonne National Laboratory. MINPACK project. March 1980.
*
*
* func points to a function from R^m --> R^n: Given a p in R^m it yields hx in R^n
* jacf points to a function implementing the Jacobian of func, whose correctness
* is to be tested. Given a p in R^m, jacf computes into the nxm matrix j the
* Jacobian of func at p. Note that row i of j corresponds to the gradient of
* the i-th component of func, evaluated at p.
* p is an input array of length m containing the point of evaluation.
* m is the number of variables
* n is the number of functions
* adata points to possible additional data and is passed uninterpreted
* to func, jacf.
* err is an array of length n. On output, err contains measures
* of correctness of the respective gradients. if there is
* no severe loss of significance, then if err[i] is 1.0 the
* i-th gradient is correct, while if err[i] is 0.0 the i-th
* gradient is incorrect. For values of err between 0.0 and 1.0,
* the categorization is less certain. In general, a value of
* err[i] greater than 0.5 indicates that the i-th gradient is
* probably correct, while a value of err[i] less than 0.5
* indicates that the i-th gradient is probably incorrect.
*
*
* The function does not perform reliably if cancellation or
* rounding errors cause a severe loss of significance in the
* evaluation of a function. therefore, none of the components
* of p should be unusually small (in particular, zero) or any
* other value which may cause loss of significance.
*/
void LEVMAR_CHKJAC(
void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata),
LM_REAL *p, int m, int n, void *adata, LM_REAL *err)
{
LM_REAL factor=LM_CNST(100.0);
LM_REAL one=LM_CNST(1.0);
LM_REAL zero=LM_CNST(0.0);
LM_REAL *fvec, *fjac, *pp, *fvecp, *buf;
register int i, j;
LM_REAL eps, epsf, temp, epsmch;
LM_REAL epslog;
int fvec_sz=n, fjac_sz=n*m, pp_sz=m, fvecp_sz=n;
epsmch=LM_REAL_EPSILON;
eps=(LM_REAL)sqrt(epsmch);
buf=(LM_REAL *)malloc((fvec_sz + fjac_sz + pp_sz + fvecp_sz)*sizeof(LM_REAL));
if(!buf){
fprintf(stderr, LCAT(LEVMAR_CHKJAC, "(): memory allocation request failed\n"));
exit(1);
}
fvec=buf;
fjac=fvec+fvec_sz;
pp=fjac+fjac_sz;
fvecp=pp+pp_sz;
/* compute fvec=func(p) */
(*func)(p, fvec, m, n, adata);
/* compute the Jacobian at p */
(*jacf)(p, fjac, m, n, adata);
/* compute pp */
for(j=0; j<m; ++j){
temp=eps*FABS(p[j]);
if(temp==zero) temp=eps;
pp[j]=p[j]+temp;
}
/* compute fvecp=func(pp) */
(*func)(pp, fvecp, m, n, adata);
epsf=factor*epsmch;
epslog=(LM_REAL)log10(eps);
for(i=0; i<n; ++i)
err[i]=zero;
for(j=0; j<m; ++j){
temp=FABS(p[j]);
if(temp==zero) temp=one;
for(i=0; i<n; ++i)
err[i]+=temp*fjac[i*m+j];
}
for(i=0; i<n; ++i){
temp=one;
if(fvec[i]!=zero && fvecp[i]!=zero && FABS(fvecp[i]-fvec[i])>=epsf*FABS(fvec[i]))
temp=eps*FABS((fvecp[i]-fvec[i])/eps - err[i])/(FABS(fvec[i])+FABS(fvecp[i]));
err[i]=one;
if(temp>epsmch && temp<eps)
err[i]=((LM_REAL)log10(temp) - epslog)/epslog;
if(temp>=eps) err[i]=zero;
}
free(buf);
return;
}
#ifdef HAVE_LAPACK
/*
* This function computes the pseudoinverse of a square matrix A
* into B using SVD. A and B can coincide
*
* The function returns 0 in case of error (e.g. A is singular),
* the rank of A if successful
*
* A, B are mxm
*
*/
static int LEVMAR_PSEUDOINVERSE(LM_REAL *A, LM_REAL *B, int m)
{
LM_REAL *buf=NULL;
int buf_sz=0;
static LM_REAL eps=LM_CNST(-1.0);
register int i, j;
LM_REAL *a, *u, *s, *vt, *work;
int a_sz, u_sz, s_sz, vt_sz, tot_sz;
LM_REAL thresh, one_over_denom;
int info, rank, worksz, *iwork, iworksz;
/* calculate required memory size */
worksz=5*m; // min worksize for GESVD
//worksz=m*(7*m+4); // min worksize for GESDD
iworksz=8*m;
a_sz=m*m;
u_sz=m*m; s_sz=m; vt_sz=m*m;
tot_sz=(a_sz + u_sz + s_sz + vt_sz + worksz)*sizeof(LM_REAL) + iworksz*sizeof(int); /* should be arranged in that order for proper doubles alignment */
buf_sz=tot_sz;
buf=(LM_REAL *)malloc(buf_sz);
if(!buf){
fprintf(stderr, RCAT("memory allocation in ", LEVMAR_PSEUDOINVERSE) "() failed!\n");
return 0; /* error */
}
a=buf;
u=a+a_sz;
s=u+u_sz;
vt=s+s_sz;
work=vt+vt_sz;
iwork=(int *)(work+worksz);
/* store A (column major!) into a */
for(i=0; i<m; i++)
for(j=0; j<m; j++)
a[i+j*m]=A[i*m+j];
/* SVD decomposition of A */
GESVD("A", "A", (int *)&m, (int *)&m, a, (int *)&m, s, u, (int *)&m, vt, (int *)&m, work, (int *)&worksz, &info);
//GESDD("A", (int *)&m, (int *)&m, a, (int *)&m, s, u, (int *)&m, vt, (int *)&m, work, (int *)&worksz, iwork, &info);
/* error treatment */
if(info!=0){
if(info<0){
fprintf(stderr, RCAT(RCAT(RCAT("LAPACK error: illegal value for argument %d of ", GESVD), "/" GESDD) " in ", LEVMAR_PSEUDOINVERSE) "()\n", -info);
}
else{
fprintf(stderr, RCAT("LAPACK error: dgesdd (dbdsdc)/dgesvd (dbdsqr) failed to converge in ", LEVMAR_PSEUDOINVERSE) "() [info=%d]\n", info);
}
free(buf);
return 0;
}
if(eps<0.0){
LM_REAL aux;
/* compute machine epsilon */
for(eps=LM_CNST(1.0); aux=eps+LM_CNST(1.0), aux-LM_CNST(1.0)>0.0; eps*=LM_CNST(0.5))
;
eps*=LM_CNST(2.0);
}
/* compute the pseudoinverse in B */
for(i=0; i<a_sz; i++) B[i]=0.0; /* initialize to zero */
for(rank=0, thresh=eps*s[0]; rank<m && s[rank]>thresh; rank++){
one_over_denom=LM_CNST(1.0)/s[rank];
for(j=0; j<m; j++)
for(i=0; i<m; i++)
B[i*m+j]+=vt[rank+i*m]*u[j+rank*m]*one_over_denom;
}
free(buf);
return rank;
}
#else // no LAPACK
/*
* This function computes the inverse of A in B. A and B can coincide
*
* The function employs LAPACK-free LU decomposition of A to solve m linear
* systems A*B_i=I_i, where B_i and I_i are the i-th columns of B and I.
*
* A and B are mxm
*
* The function returns 0 in case of error, 1 if successful
*
*/
static int LEVMAR_LUINVERSE(LM_REAL *A, LM_REAL *B, int m)
{
void *buf=NULL;
//int buf_sz=0;
register int i, j, k, l;
int *idx, maxi=-1, idx_sz, a_sz, x_sz, work_sz, tot_sz;
LM_REAL *a, *x, *work, max, sum, tmp;
/* calculate required memory size */
idx_sz=m;
a_sz=m*m;
x_sz=m;
work_sz=m;
tot_sz=(a_sz + x_sz + work_sz)*sizeof(LM_REAL) + idx_sz*sizeof(int); /* should be arranged in that order for proper doubles alignment */
//buf_sz=tot_sz;
buf=(void *)malloc(tot_sz);
if(!buf){
fprintf(stderr, RCAT("memory allocation in ", LEVMAR_LUINVERSE) "() failed!\n");
return 0; /* error */
}
a=buf;
x=a+a_sz;
work=x+x_sz;
idx=(int *)(work+work_sz);
/* avoid destroying A by copying it to a */
for(i=0; i<a_sz; ++i) a[i]=A[i];
/* compute the LU decomposition of a row permutation of matrix a; the permutation itself is saved in idx[] */
for(i=0; i<m; ++i){
max=0.0;
for(j=0; j<m; ++j)
if((tmp=FABS(a[i*m+j]))>max)
max=tmp;
if(max==0.0){
fprintf(stderr, RCAT("Singular matrix A in ", LEVMAR_LUINVERSE) "()!\n");
free(buf);
return 0;
}
work[i]=LM_CNST(1.0)/max;
}
for(j=0; j<m; ++j){
for(i=0; i<j; ++i){
sum=a[i*m+j];
for(k=0; k<i; ++k)
sum-=a[i*m+k]*a[k*m+j];
a[i*m+j]=sum;
}
max=0.0;
for(i=j; i<m; ++i){
sum=a[i*m+j];
for(k=0; k<j; ++k)
sum-=a[i*m+k]*a[k*m+j];
a[i*m+j]=sum;
if((tmp=work[i]*FABS(sum))>=max){
max=tmp;
maxi=i;
}
}
if(j!=maxi){
for(k=0; k<m; ++k){
tmp=a[maxi*m+k];
a[maxi*m+k]=a[j*m+k];
a[j*m+k]=tmp;
}
work[maxi]=work[j];
}
idx[j]=maxi;
if(a[j*m+j]==0.0)
a[j*m+j]=LM_REAL_EPSILON;
if(j!=m-1){
tmp=LM_CNST(1.0)/(a[j*m+j]);
for(i=j+1; i<m; ++i)
a[i*m+j]*=tmp;
}
}
/* The decomposition has now replaced a. Solve the m linear systems using
* forward and back substitution
*/
for(l=0; l<m; ++l){
for(i=0; i<m; ++i) x[i]=0.0;
x[l]=LM_CNST(1.0);
for(i=k=0; i<m; ++i){
j=idx[i];
sum=x[j];
x[j]=x[i];
if(k!=0)
for(j=k-1; j<i; ++j)
sum-=a[i*m+j]*x[j];
else
if(sum!=0.0)
k=i+1;
x[i]=sum;
}
for(i=m-1; i>=0; --i){
sum=x[i];
for(j=i+1; j<m; ++j)
sum-=a[i*m+j]*x[j];
x[i]=sum/a[i*m+i];
}
for(i=0; i<m; ++i)
B[i*m+l]=x[i];
}
free(buf);
return 1;
}
#endif /* HAVE_LAPACK */
/*
* This function computes in C the covariance matrix corresponding to a least
* squares fit. JtJ is the approximate Hessian at the solution (i.e. J^T*J, where
* J is the Jacobian at the solution), sumsq is the sum of squared residuals
* (i.e. goodnes of fit) at the solution, m is the number of parameters (variables)
* and n the number of observations. JtJ can coincide with C.
*
* if JtJ is of full rank, C is computed as sumsq/(n-m)*(JtJ)^-1
* otherwise and if LAPACK is available, C=sumsq/(n-r)*(JtJ)^+
* where r is JtJ's rank and ^+ denotes the pseudoinverse
* The diagonal of C is made up from the estimates of the variances
* of the estimated regression coefficients.
* See the documentation of routine E04YCF from the NAG fortran lib
*
* The function returns the rank of JtJ if successful, 0 on error
*
* A and C are mxm
*
*/
int LEVMAR_COVAR(LM_REAL *JtJ, LM_REAL *C, LM_REAL sumsq, int m, int n)
{
register int i;
int rnk;
LM_REAL fact;
#ifdef HAVE_LAPACK
rnk=LEVMAR_PSEUDOINVERSE(JtJ, C, m);
if(!rnk) return 0;
#else
#ifdef _MSC_VER
#pragma message("LAPACK not available, LU will be used for matrix inversion when computing the covariance; this might be unstable at times")
#else
#warning LAPACK not available, LU will be used for matrix inversion when computing the covariance; this might be unstable at times
#endif // _MSC_VER
rnk=LEVMAR_LUINVERSE(JtJ, C, m);
if(!rnk) return 0;
rnk=m; /* assume full rank */
#endif /* HAVE_LAPACK */
fact=sumsq/(LM_REAL)(n-rnk);
for(i=0; i<m*m; ++i)
C[i]*=fact;
return rnk;
}
/* standard deviation of the best-fit parameter i.
* covar is the mxm covariance matrix of the best-fit parameters (see also LEVMAR_COVAR()).
*
* The standard deviation is computed as \sigma_{i} = \sqrt{C_{ii}}
*/
LM_REAL LEVMAR_STDDEV(LM_REAL *covar, int m, int i)
{
return (LM_REAL)sqrt(covar[i*m+i]);
}
/* Pearson's correlation coefficient of the best-fit parameters i and j.
* covar is the mxm covariance matrix of the best-fit parameters (see also LEVMAR_COVAR()).
*
* The coefficient is computed as \rho_{ij} = C_{ij} / sqrt(C_{ii} C_{jj})
*/
LM_REAL LEVMAR_CORCOEF(LM_REAL *covar, int m, int i, int j)
{
return (LM_REAL)(covar[i*m+j]/sqrt(covar[i*m+i]*covar[j*m+j]));
}
/* coefficient of determination.
* see http://en.wikipedia.org/wiki/Coefficient_of_determination
*/
LM_REAL LEVMAR_R2(void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),
LM_REAL *p, LM_REAL *x, int m, int n, void *adata)
{
register int i;
register LM_REAL tmp;
LM_REAL SSerr, // sum of squared errors, i.e. residual sum of squares \sum_i (x_i-hx_i)^2
SStot, // \sum_i (x_i-xavg)^2
*hx, xavg;
if((hx=(LM_REAL *)malloc(n*sizeof(LM_REAL)))==NULL){
fprintf(stderr, RCAT("memory allocation request failed in ", LEVMAR_R2) "()\n");
exit(1);
}
/* hx=f(p) */
(*func)(p, hx, m, n, adata);
for(i=n, tmp=0.0; i-->0; )
tmp+=x[i];
xavg=tmp/(LM_REAL)n;
if(x)
for(i=n, SSerr=SStot=0.0; i-->0; ){
tmp=x[i]-hx[i];
SSerr+=tmp*tmp;
tmp=x[i]-xavg;
SStot+=tmp*tmp;
}
else /* x==0 */
for(i=n, SSerr=SStot=0.0; i-->0; ){
tmp=-hx[i];
SSerr+=tmp*tmp;
tmp=-xavg;
SStot+=tmp*tmp;
}
free(hx);
return LM_CNST(1.0) - SSerr/SStot;
}
/* check box constraints for consistency */
int LEVMAR_BOX_CHECK(LM_REAL *lb, LM_REAL *ub, int m)
{
register int i;
if(!lb || !ub) return 1;
for(i=0; i<m; ++i)
if(lb[i]>ub[i]) return 0;
return 1;
}
#ifdef HAVE_LAPACK
/* compute the Cholesky decomposition of C in W, s.t. C=W^t W and W is upper triangular */
int LEVMAR_CHOLESKY(LM_REAL *C, LM_REAL *W, int m)
{
register int i, j;
int info;
/* copy weights array C to W so that LAPACK won't destroy it;
* C is assumed symmetric, hence no transposition is needed
*/
for(i=0, j=m*m; i<j; ++i)
W[i]=C[i];
/* Cholesky decomposition */
POTF2("L", (int *)&m, W, (int *)&m, (int *)&info);
/* error treatment */
if(info!=0){
if(info<0){
fprintf(stderr, "LAPACK error: illegal value for argument %d of dpotf2 in %s\n", -info, LCAT(LEVMAR_CHOLESKY, "()"));
}
else{
fprintf(stderr, "LAPACK error: the leading minor of order %d is not positive definite,\n%s()\n", info,
RCAT("and the Cholesky factorization could not be completed in ", LEVMAR_CHOLESKY));
}
return LM_ERROR;
}
/* the decomposition is in the lower part of W (in column-major order!).
* zeroing the upper part makes it lower triangular which is equivalent to
* upper triangular in row-major order
*/
for(i=0; i<m; i++)
for(j=i+1; j<m; j++)
W[i+j*m]=0.0;
return 0;
}
#endif /* HAVE_LAPACK */
/* Compute e=x-y for two n-vectors x and y and return the squared L2 norm of e.
* e can coincide with either x or y; x can be NULL, in which case it is assumed
* to be equal to the zero vector.
* Uses loop unrolling and blocking to reduce bookkeeping overhead & pipeline
* stalls and increase instruction-level parallelism; see http://www.abarnett.demon.co.uk/tutorial.html
*/
LM_REAL LEVMAR_L2NRMXMY(LM_REAL *e, LM_REAL *x, LM_REAL *y, int n)
{
const int blocksize=8, bpwr=3; /* 8=2^3 */
register int i;
int j1, j2, j3, j4, j5, j6, j7;
int blockn;
register LM_REAL sum0=0.0, sum1=0.0, sum2=0.0, sum3=0.0;
/* n may not be divisible by blocksize,
* go as near as we can first, then tidy up.
*/
blockn = (n>>bpwr)<<bpwr; /* (n / blocksize) * blocksize; */
/* unroll the loop in blocks of `blocksize'; looping downwards gains some more speed */
if(x){
for(i=blockn-1; i>0; i-=blocksize){
e[i ]=x[i ]-y[i ]; sum0+=e[i ]*e[i ];
j1=i-1; e[j1]=x[j1]-y[j1]; sum1+=e[j1]*e[j1];
j2=i-2; e[j2]=x[j2]-y[j2]; sum2+=e[j2]*e[j2];
j3=i-3; e[j3]=x[j3]-y[j3]; sum3+=e[j3]*e[j3];
j4=i-4; e[j4]=x[j4]-y[j4]; sum0+=e[j4]*e[j4];
j5=i-5; e[j5]=x[j5]-y[j5]; sum1+=e[j5]*e[j5];
j6=i-6; e[j6]=x[j6]-y[j6]; sum2+=e[j6]*e[j6];
j7=i-7; e[j7]=x[j7]-y[j7]; sum3+=e[j7]*e[j7];
}
/*
* There may be some left to do.
* This could be done as a simple for() loop,
* but a switch is faster (and more interesting)
*/
i=blockn;
if(i<n){
/* Jump into the case at the place that will allow
* us to finish off the appropriate number of items.
*/
switch(n - i){
case 7 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;
case 6 : e[i]=x[i]-y[i]; sum1+=e[i]*e[i]; ++i;
case 5 : e[i]=x[i]-y[i]; sum2+=e[i]*e[i]; ++i;
case 4 : e[i]=x[i]-y[i]; sum3+=e[i]*e[i]; ++i;
case 3 : e[i]=x[i]-y[i]; sum0+=e[i]*e[i]; ++i;
case 2 : e[i]=x[i]-y[i]; sum1+=e[i]*e[i]; ++i;
case 1 : e[i]=x[i]-y[i]; sum2+=e[i]*e[i]; //++i;
}
}
}
else{ /* x==0 */
for(i=blockn-1; i>0; i-=blocksize){
e[i ]=-y[i ]; sum0+=e[i ]*e[i ];
j1=i-1; e[j1]=-y[j1]; sum1+=e[j1]*e[j1];
j2=i-2; e[j2]=-y[j2]; sum2+=e[j2]*e[j2];
j3=i-3; e[j3]=-y[j3]; sum3+=e[j3]*e[j3];
j4=i-4; e[j4]=-y[j4]; sum0+=e[j4]*e[j4];
j5=i-5; e[j5]=-y[j5]; sum1+=e[j5]*e[j5];
j6=i-6; e[j6]=-y[j6]; sum2+=e[j6]*e[j6];
j7=i-7; e[j7]=-y[j7]; sum3+=e[j7]*e[j7];
}
/*
* There may be some left to do.
* This could be done as a simple for() loop,
* but a switch is faster (and more interesting)
*/
i=blockn;
if(i<n){
/* Jump into the case at the place that will allow
* us to finish off the appropriate number of items.
*/
switch(n - i){
case 7 : e[i]=-y[i]; sum0+=e[i]*e[i]; ++i;
case 6 : e[i]=-y[i]; sum1+=e[i]*e[i]; ++i;
case 5 : e[i]=-y[i]; sum2+=e[i]*e[i]; ++i;
case 4 : e[i]=-y[i]; sum3+=e[i]*e[i]; ++i;
case 3 : e[i]=-y[i]; sum0+=e[i]*e[i]; ++i;
case 2 : e[i]=-y[i]; sum1+=e[i]*e[i]; ++i;
case 1 : e[i]=-y[i]; sum2+=e[i]*e[i]; //++i;
}
}
}
return sum0+sum1+sum2+sum3;
}
/* undefine everything. THIS MUST REMAIN AT THE END OF THE FILE */
#undef POTF2
#undef GESVD
#undef GESDD
#undef GEMM
#undef LEVMAR_PSEUDOINVERSE
#undef LEVMAR_LUINVERSE
#undef LEVMAR_BOX_CHECK
#undef LEVMAR_CHOLESKY
#undef LEVMAR_COVAR
#undef LEVMAR_STDDEV
#undef LEVMAR_CORCOEF
#undef LEVMAR_R2
#undef LEVMAR_CHKJAC
#undef LEVMAR_FDIF_FORW_JAC_APPROX
#undef LEVMAR_FDIF_CENT_JAC_APPROX
#undef LEVMAR_TRANS_MAT_MAT_MULT
#undef LEVMAR_L2NRMXMY

View File

@@ -73,7 +73,7 @@ int CodeEditor::lineNumberAreaWidth()
++digits;
}
int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
int space = 3 + fontMetrics().horizontalAdvance(QLatin1Char('9')) * digits;
return space;
}
@@ -117,7 +117,8 @@ void CodeEditor::highlightCurrentLine()
if (!isReadOnly()) {
QTextEdit::ExtraSelection selection;
selection.format.setBackground(lineAreaColor);
selection.format.setBackground(QColor(Qt::lightGray));
selection.format.setForeground(QColor(Qt::black));
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
selection.cursor = textCursor();
selection.cursor.clearSelection();

View File

@@ -0,0 +1,252 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtWidgets>
#include "flowlayout.h"
//! [1]
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
: m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
//! [1]
//! [2]
FlowLayout::~FlowLayout()
{
QLayoutItem *item;
while ((item = takeAt(0)))
delete item;
}
//! [2]
//! [3]
void FlowLayout::addItem(QLayoutItem *item)
{
itemList.append(item);
}
//! [3]
//! [4]
int FlowLayout::horizontalSpacing() const
{
if (m_hSpace >= 0) {
return m_hSpace;
} else {
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
}
}
int FlowLayout::verticalSpacing() const
{
if (m_vSpace >= 0) {
return m_vSpace;
} else {
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}
}
//! [4]
//! [5]
int FlowLayout::count() const
{
return itemList.size();
}
QLayoutItem *FlowLayout::itemAt(int index) const
{
return itemList.value(index);
}
QLayoutItem *FlowLayout::takeAt(int index)
{
if (index >= 0 && index < itemList.size())
return itemList.takeAt(index);
return nullptr;
}
//! [5]
//! [6]
Qt::Orientations FlowLayout::expandingDirections() const
{
return { };
}
//! [6]
//! [7]
bool FlowLayout::hasHeightForWidth() const
{
return true;
}
int FlowLayout::heightForWidth(int width) const
{
int height = doLayout(QRect(0, 0, width, 0), true);
return height;
}
//! [7]
//! [8]
void FlowLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
doLayout(rect, false);
}
QSize FlowLayout::sizeHint() const
{
return minimumSize();
}
QSize FlowLayout::minimumSize() const
{
QSize size;
for (const QLayoutItem *item : qAsConst(itemList))
size = size.expandedTo(item->minimumSize());
const QMargins margins = contentsMargins();
size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
return size;
}
//! [8]
//! [9]
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
{
int left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
int x = effectiveRect.x();
int y = effectiveRect.y();
int lineHeight = 0;
//! [9]
QList<int> lineHeights;
for (QLayoutItem *item : qAsConst(itemList)) {
const QWidget *wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
int spaceY = verticalSpacing();
if (spaceY == -1)
spaceY = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX;
lineHeights << lineHeight;
lineHeight = 0;
}
x = nextX;
lineHeight = qMax(lineHeight, item->sizeHint().height());
}
if (lineHeight > 0) {
lineHeights << lineHeight;
}
x = effectiveRect.x();
y = effectiveRect.y();
int row = 0;
//! [10]
for (QLayoutItem *item : qAsConst(itemList)) {
lineHeight = lineHeights.value(row, item->sizeHint().height());
const QWidget *wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
int spaceY = verticalSpacing();
if (spaceY == -1)
spaceY = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
//! [10]
//! [11]
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX;
++row;
}
if (!testOnly)
item->setGeometry(QRect(QPoint(x, y + (lineHeight - item->sizeHint().height()) / 2 ), item->sizeHint()));
x = nextX;
}
return y + lineHeight - rect.y() + bottom;
}
//! [11]
//! [12]
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{
QObject *parent = this->parent();
if (!parent) {
return -1;
} else if (parent->isWidgetType()) {
QWidget *pw = static_cast<QWidget *>(parent);
return pw->style()->pixelMetric(pm, nullptr, pw);
} else {
return static_cast<QLayout *>(parent)->spacing();
}
}
//! [12]

View File

@@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef FLOWLAYOUT_H
#define FLOWLAYOUT_H
#include <QLayout>
#include <QRect>
#include <QStyle>
//! [0]
class FlowLayout : public QLayout
{
public:
explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayout();
void addItem(QLayoutItem *item) override;
int horizontalSpacing() const;
int verticalSpacing() const;
Qt::Orientations expandingDirections() const override;
bool hasHeightForWidth() const override;
int heightForWidth(int) const override;
int count() const override;
QLayoutItem *itemAt(int index) const override;
QSize minimumSize() const override;
void setGeometry(const QRect &rect) override;
QSize sizeHint() const override;
QLayoutItem *takeAt(int index) override;
private:
int doLayout(const QRect &rect, bool testOnly) const;
int smartSpacing(QStyle::PixelMetric pm) const;
QList<QLayoutItem *> itemList;
int m_hSpace;
int m_vSpace;
};
//! [0]
#endif // FLOWLAYOUT_H

View File

@@ -108,14 +108,14 @@ void QxtSpanSliderPrivate::setupPainter(QPainter* painter, Qt::Orientation orien
{
QColor highlight = qxt_p().palette().color(QPalette::Highlight);
QLinearGradient gradient(x1, y1, x2, y2);
gradient.setColorAt(0, highlight.dark(120));
gradient.setColorAt(1, highlight.light(108));
gradient.setColorAt(0, highlight.darker(120));
gradient.setColorAt(1, highlight.lighter(108));
painter->setBrush(gradient);
if (orientation == Qt::Horizontal)
painter->setPen(QPen(highlight.dark(130), 0));
painter->setPen(QPen(highlight.darker(130), 0));
else
painter->setPen(QPen(highlight.dark(150), 0));
painter->setPen(QPen(highlight.darker(150), 0));
}
void QxtSpanSliderPrivate::drawSpan(QStylePainter* painter, const QRect& rect) const
@@ -132,7 +132,7 @@ void QxtSpanSliderPrivate::drawSpan(QStylePainter* painter, const QRect& rect) c
groove.adjust(0, 0, 0, -1);
// pen & brush
painter->setPen(QPen(p->palette().color(QPalette::Dark).light(110), 0));
painter->setPen(QPen(p->palette().color(QPalette::Dark).lighter(110), 0));
if (opt.orientation == Qt::Horizontal)
setupPainter(painter, opt.orientation, groove.center().x(), groove.top(), groove.center().x(), groove.bottom());
else

View File

@@ -184,7 +184,7 @@ bool GoogleDrive::createFolder(QString path) {
return true;
}
// TODO(gille): This only supports directories in the root. Fix that.
QStringList parts = path.split("/", QString::SkipEmptyParts);
QStringList parts = path.split("/", Qt::SkipEmptyParts);
QString dir_name = parts.back();
FileInfo* parent_fi = WalkFileInfo(path, true);
if (parent_fi == NULL) {
@@ -241,7 +241,7 @@ bool GoogleDrive::createFolder(QString path) {
GoogleDrive::FileInfo* GoogleDrive::WalkFileInfo(const QString& path,
bool foo) {
QStringList parts = path.split("/", QString::SkipEmptyParts);
QStringList parts = path.split("/", Qt::SkipEmptyParts);
FileInfo* target = root_dir_.data();
// Lets walk!
for (QStringList::iterator it = parts.begin(); it != parts.end(); ++it) {
@@ -746,7 +746,7 @@ GoogleDrive::FileInfo* GoogleDrive::BuildDirectoriesForAthleteDirectory(
return NULL;
}
printd("GC_GOOGLE_DRIVE_FOLDER_ID: %s\n", id.toStdString().c_str());
QStringList parts = path.split("/", QString::SkipEmptyParts);
QStringList parts = path.split("/", Qt::SkipEmptyParts);
FileInfo *fi = root_dir_.data();
for (QStringList::iterator it = parts.begin(); it != parts.end(); ++it) {

View File

@@ -160,7 +160,7 @@ IntervalColumnChooser::IntervalColumnChooser(QList<QString>&logicalHeadings)
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint | Qt::Tool);
clicked = new QSignalMapper(this); // maps each button click event
connect(clicked, SIGNAL(mapped(const QString &)), this, SLOT(buttonClicked(const QString &)));
connect(clicked, &QSignalMapper::mappedString, this, &IntervalColumnChooser::buttonClicked);
buttons = new QGridLayout(this);
buttons->setSpacing(0);

View File

@@ -216,7 +216,7 @@ bool KentUniversity::createFolder(QString path) {
return true;
}
// TODO(gille): This only supports directories in the root. Fix that.
QStringList parts = path.split("/", QString::SkipEmptyParts);
QStringList parts = path.split("/", Qt::SkipEmptyParts);
QString dir_name = parts.back();
FileInfo* parent_fi = WalkFileInfo(path, true);
if (parent_fi == NULL) {
@@ -273,7 +273,7 @@ bool KentUniversity::createFolder(QString path) {
KentUniversity::FileInfo* KentUniversity::WalkFileInfo(const QString& path,
bool foo) {
QStringList parts = path.split("/", QString::SkipEmptyParts);
QStringList parts = path.split("/", Qt::SkipEmptyParts);
FileInfo* target = root_dir_.data();
// Lets walk!
for (QStringList::iterator it = parts.begin(); it != parts.end(); ++it) {
@@ -772,7 +772,7 @@ KentUniversity::FileInfo* KentUniversity::BuildDirectoriesForAthleteDirectory(
return NULL;
}
printd("GC_UOK_GOOGLE_DRIVE_FOLDER_ID: %s\n", id.toStdString().c_str());
QStringList parts = path.split("/", QString::SkipEmptyParts);
QStringList parts = path.split("/", Qt::SkipEmptyParts);
FileInfo *fi = root_dir_.data();
for (QStringList::iterator it = parts.begin(); it != parts.end(); ++it) {

View File

@@ -23,7 +23,10 @@
#include "RideFile.h"
struct KmlFileReader : public RideFileReader {
virtual RideFile *openRideFile(QFile &, QStringList &, QList<RideFile*>* =0) const { return NULL; } // does not support reading
virtual RideFile *openRideFile(QFile &, QStringList &errors, QList<RideFile*>* =0) const {
errors << QString("kml files are not supported for import"); // does not support reading
return NULL;
}
bool writeRideFile(Context *, const RideFile *ride, QFile &file) const;
bool hasWrite() const { return true; }
};

View File

@@ -154,7 +154,7 @@ QwtScaleDiv LogTimeScaleEngine::divideScale(double x1, double x2,
QwtScaleDiv scaleDiv;
if ( stepSize != 0.0 )
{
QwtValueList ticks[QwtScaleDiv::NTickTypes];
QList<double> ticks[QwtScaleDiv::NTickTypes];
buildTicks(interval, stepSize, maxMinSteps, ticks);
scaleDiv = QwtScaleDiv(interval, ticks);
@@ -168,7 +168,7 @@ QwtScaleDiv LogTimeScaleEngine::divideScale(double x1, double x2,
void LogTimeScaleEngine::buildTicks(
const QwtDoubleInterval& interval, double stepSize, int maxMinSteps,
QwtValueList ticks[QwtScaleDiv::NTickTypes]) const
QList<double> ticks[QwtScaleDiv::NTickTypes]) const
{
const QwtDoubleInterval boundingInterval =
align(interval, stepSize);
@@ -210,12 +210,12 @@ tick_info_t tick_info[] = {
{ -1.0, NULL }
};
QwtValueList LogTimeScaleEngine::buildMajorTicks(
QList<double> LogTimeScaleEngine::buildMajorTicks(
const QwtDoubleInterval &interval, double stepSize) const
{
(void) interval;
(void) stepSize;
QwtValueList ticks;
QList<double> ticks;
tick_info_t *walker = tick_info;
while (walker->label) {
ticks += walker->x;
@@ -224,14 +224,14 @@ QwtValueList LogTimeScaleEngine::buildMajorTicks(
return ticks;
}
QwtValueList LogTimeScaleEngine::buildMinorTicks(
const QwtValueList &majorTicks,
QList<double> LogTimeScaleEngine::buildMinorTicks(
const QList<double> &majorTicks,
int maxMinSteps, double stepSize) const
{
(void) majorTicks;
(void) maxMinSteps;
(void) stepSize;
QwtValueList minorTicks;
QList<double> minorTicks;
return minorTicks;
}

View File

@@ -53,13 +53,13 @@ class LogTimeScaleEngine : public QwtScaleEngine
void buildTicks(
const QwtDoubleInterval &, double stepSize, int maxMinSteps,
QwtValueList ticks[QwtScaleDiv::NTickTypes]) const;
QList<double> ticks[QwtScaleDiv::NTickTypes]) const;
QwtValueList buildMinorTicks(
const QwtValueList& majorTicks,
QList<double> buildMinorTicks(
const QList<double>& majorTicks,
int maxMinMark, double step) const;
QwtValueList buildMajorTicks(
QList<double> buildMajorTicks(
const QwtDoubleInterval &interval, double stepSize) const;
};

View File

@@ -33,7 +33,7 @@ NewMainWindow::NewMainWindow(QApplication *app) : QMainWindow(NULL), state(Inact
setCentralWidget(main);
layout = new QVBoxLayout(main);
layout->setSpacing(0);
layout->setMargin(0);
layout->setContentsMargins(QMargins());
// toolbar
setupToolbar();

View File

@@ -2223,7 +2223,6 @@ OverviewWindow::configChanged(qint32)
// text edit colors
QPalette palette;
palette.setColor(QPalette::Window, GColor(COVERVIEWBACKGROUND));
palette.setColor(QPalette::Background, GColor(COVERVIEWBACKGROUND));
// only change base if moved away from white plots
// which is a Mac thing

View File

@@ -48,26 +48,26 @@ PerfPlot::PerfPlot() : STScurve(NULL), LTScurve(NULL), SBcurve(NULL), DAYcurve(N
{
xsd = new PPTimeScaleDraw(QDateTime());
xsd->setTickLength(QwtScaleDiv::MajorTick, 3);
setAxisScaleDraw(QwtPlot::xBottom, xsd);
setAxisScaleDraw(QwtAxis::XBottom, xsd);
insertLegend(new QwtLegend(), QwtPlot::BottomLegend);
setAxisTitle(yLeft, tr("Exponentially Weighted Average Stress"));
setAxisTitle(xBottom, tr("Time (days)"));
setAxisTitle(yRight, tr("Daily Stress"));
enableAxis(yRight, true);
setAxisTitle(YLeft, tr("Exponentially Weighted Average Stress"));
setAxisTitle(XBottom, tr("Time (days)"));
setAxisTitle(QwtAxis::YRight, tr("Daily Stress"));
setAxisVisible(QwtAxis::YRight, true);
static_cast<QwtPlotCanvas*>(canvas())->setFrameStyle(QFrame::NoFrame);
setAxisMaxMinor(xBottom, 0);
setAxisMaxMinor(yLeft, 0);
setAxisMaxMinor(yRight, 0);
setAxisMaxMinor(XBottom, 0);
setAxisMaxMinor(YLeft, 0);
setAxisMaxMinor(QwtAxis::YRight, 0);
QwtScaleDraw *sd = new QwtScaleDraw;
sd->setTickLength(QwtScaleDiv::MajorTick, 3);
setAxisScaleDraw(QwtPlot::yLeft, sd);
setAxisScaleDraw(QwtAxis::YLeft, sd);
sd = new QwtScaleDraw;
sd->setTickLength(QwtScaleDiv::MajorTick, 3);
setAxisScaleDraw(QwtPlot::yRight, sd);
setAxisScaleDraw(QwtAxis::YRight, sd);
grid = new QwtPlotGrid();
grid->attach(this);
@@ -99,7 +99,7 @@ void PerfPlot::plot() {
int num, tics;
tics = 42;
setAxisScale(yLeft, _sc->min(), _sc->max());
setAxisScale(YLeft, _sc->min(), _sc->max());
num = xmax - xmin;
/*
@@ -117,8 +117,8 @@ void PerfPlot::plot() {
} else if (num < 364) {
tics = 27;
}
setAxisScale(xBottom, xmin, xmax,tics);
axisWidget(xBottom)->update();
setAxisScale(XBottom, xmin, xmax,tics);
axisWidget(XBottom)->update();
// set base
xsd->setBase(startDate);
@@ -142,7 +142,7 @@ void PerfPlot::plot() {
// |
// V
DAYcurve->setSamples(_sc->getDays()+xmin -1 ,_sc->getDAYvalues()+xmin,num);
DAYcurve->setYAxis(yRight);
DAYcurve->setYAxis(QwtAxis::YRight);
DAYcurve->attach(this);
if (STScurve) {
@@ -186,7 +186,7 @@ void PerfPlot::plot() {
SBcurve->setSamples(_sc->getDays()+xmin,_sc->getSBvalues()+xmin,num);
SBcurve->attach(this);
axisWidget(QwtPlot::xBottom)->update();
axisWidget(QwtAxis::XBottom)->update();
replot();
}

View File

@@ -100,7 +100,7 @@ PerformanceManagerWindow::PerformanceManagerWindow(Context *context) :
vlayout->addLayout(PMPickerLayout);
setLayout(vlayout);
PMpicker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft,
PMpicker = new QwtPlotPicker(QwtAxis::XBottom, QwtAxis::YLeft,
QwtPicker::VLineRubberBand,
QwtPicker::AlwaysOff, perfplot->canvas());
PMpicker->setStateMachine(new QwtPickerDragPointMachine);
@@ -152,7 +152,6 @@ void PerformanceManagerWindow::configChanged()
QPalette palette;
palette.setBrush(QPalette::Window, QBrush(GColor(CPLOTBACKGROUND)));
palette.setBrush(QPalette::Background, QBrush(GColor(CPLOTBACKGROUND)));
palette.setBrush(QPalette::Base, QBrush(GColor(CPLOTBACKGROUND)));
palette.setColor(QPalette::WindowText, GCColor::invertColor(GColor(CPLOTBACKGROUND)));
palette.setColor(QPalette::Text, GCColor::invertColor(GColor(CPLOTBACKGROUND)));
@@ -283,7 +282,7 @@ void PerformanceManagerWindow::replot()
void
PerformanceManagerWindow::PMpickerMoved(const QPoint &pos)
{
double day = perfplot->invTransform(QwtPlot::xBottom, pos.x());
double day = perfplot->invTransform(QwtAxis::XBottom, pos.x());
QDateTime date;
double sts, lts, sb;

View File

@@ -24,7 +24,7 @@ RaceRider::RaceRider(QWidget *parent, QColor color, QString name, QString id) :
{
QPalette pal = palette();
//QColor RGB = color.convertTo(QColor::Rgb);
pal.setColor(QPalette::Normal, QPalette::Background, color);
pal.setColor(QPalette::Normal, QPalette::Window, color);
pal.setColor(QPalette::Normal, QPalette::Base, color);
pal.setColor(QPalette::Normal, QPalette::Button, color);
pal.setColor(QPalette::Normal, QPalette::Text, Qt::black);

View File

@@ -235,7 +235,7 @@ TodaysPlan::readdir(QString path, QStringList &errors, QDateTime from, QDateTime
// Prepare the Search Payload for First Call to Search
QString userId = getSetting(GC_TODAYSPLAN_ATHLETE_ID, "").toString();
// application/json
QByteArray jsonString;
QString jsonString;
jsonString += "{\"criteria\": {";
if (userId.length()>0)
jsonString += "\"user\": "+ QString("%1").arg(userId) +", ";
@@ -248,13 +248,15 @@ TodaysPlan::readdir(QString path, QStringList &errors, QDateTime from, QDateTime
jsonString += "\"opts\": 1 "; // without fields description
jsonString += "}";
printd("request: %s\n", jsonString.toStdString().c_str());
printd("request: %s\n", jsonString.toUtf8().toStdString().c_str());
QByteArray jsonStringDataSize = QByteArray::number(jsonString.size());
QByteArray jsonStringAsUTF8 = jsonString.toUtf8();
QByteArray jsonStringDataSize = QByteArray::number(jsonStringAsUTF8.size());
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");
request.setRawHeader("Content-Length", jsonStringDataSize);
reply = nam->post(request, jsonString);
reply = nam->post(request, jsonStringAsUTF8);
} else {
// get further pages of the Search
reply = nam->get(request);
@@ -395,7 +397,7 @@ TodaysPlan::writeFile(QByteArray &data, QString remotename, RideFile *ride)
// MULTIPART *****************
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QString boundary = QVariant(qrand()).toString()+QVariant(qrand()).toString()+QVariant(qrand()).toString();
QString boundary = QVariant(QRandomGenerator::global()->generate()).toString()+QVariant(QRandomGenerator::global()->generate()).toString()+QVariant(QRandomGenerator::global()->generate()).toString();
multiPart->setBoundary(boundary.toLatin1());
request.setRawHeader("Authorization", (QString("Bearer %1").arg(token)).toLatin1());

View File

@@ -88,7 +88,7 @@ TodaysPlanBodyMeasures::getBodyMeasures(QString &error, QDateTime from, QDateTim
// Prepare the Search Payload for First Call to Search
QString userId = appsettings->cvalue(context->athlete->cyclist, GC_TODAYSPLAN_ATHLETE_ID, "").toString();
// application/json
QByteArray jsonString;
QString jsonString;
jsonString += "{\"criteria\": { ";
if (userId.length()>0)
jsonString += " \"userIds\": [ "+ QString("%1").arg(userId) +" ], ";
@@ -99,11 +99,13 @@ TodaysPlanBodyMeasures::getBodyMeasures(QString &error, QDateTime from, QDateTim
jsonString += "\"fields\": [\"att.ts\",\"att.weight\", \"att.fat\",\"att.muscleMass\",\"att.boneMass\",\"att.fatMass\", \"att.height\" , \"att.source\"] ";
jsonString += "}";
QByteArray jsonStringDataSize = QByteArray::number(jsonString.size());
QByteArray jsonStringAsUTF8 = jsonString.toUtf8();
QByteArray jsonStringDataSize = QByteArray::number(jsonStringAsUTF8.size());
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");
request.setRawHeader("Content-Length", jsonStringDataSize);
reply = nam->post(request, jsonString);
reply = nam->post(request, jsonStringAsUTF8);
} else {
// get further pages of the Search
reply = nam->get(request);

View File

@@ -261,8 +261,8 @@ TodaysPlanWorkoutDownload::downloadFiles()
QString filename;
ErgFile *p = ErgFile::fromContent(content, context);
if (p->Filename != "") {
filename = workoutDir + "/TP-" + p->Filename.replace("/", "-").simplified();
if (p->originalFilename() != "") {
filename = workoutDir + "/TP-" + p->originalFilename().replace("/", "-").simplified();
} else {
filename = workoutDir + "/TP-Workout-" + current->text(1).replace(" ", "_") + ".erg";
}
@@ -298,7 +298,7 @@ TodaysPlanWorkoutDownload::downloadFiles()
downloads++;
current->setText(5, tr("Saved")); QApplication::processEvents();
trainDB->importWorkout(filename, p); // add to library
trainDB->importWorkout(filename, *p); // add to library
} else {
@@ -367,7 +367,7 @@ TodaysPlanWorkoutDownload::getFileList(QString &error, QDateTime from, QDateTime
// Prepare the Search Payload for First Call to Search
QString userId = appsettings->cvalue(context->athlete->cyclist, GC_TODAYSPLAN_ATHLETE_ID, "").toString();
// application/json
QByteArray jsonString;
QString jsonString;
jsonString += "{\"criteria\": {";
if (userId.length()>0)
jsonString += "\"user\": "+ QString("%1").arg(userId) +", ";
@@ -379,11 +379,13 @@ TodaysPlanWorkoutDownload::getFileList(QString &error, QDateTime from, QDateTime
jsonString += "\"opts\": 1 ";
jsonString += "}";
QByteArray jsonStringDataSize = QByteArray::number(jsonString.size());
QByteArray jsonStringAsUTF8 = jsonString.toUtf8();
QByteArray jsonStringDataSize = QByteArray::number(jsonStringAsUTF8.size());
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");
request.setRawHeader("Content-Length", jsonStringDataSize);
reply = nam->post(request, jsonString);
reply = nam->post(request, jsonStringAsUTF8);
} else {
// get further pages of the Search
reply = nam->get(request);

View File

@@ -44,14 +44,14 @@ WeeklySummaryWindow::WeeklySummaryWindow(bool useMetricUnits,
// set up the weekly distance / duration plot:
weeklyPlot = new QwtPlot();
weeklyPlot->enableAxis(QwtPlot::yRight, true);
weeklyPlot->setAxisMaxMinor(QwtPlot::xBottom,0);
weeklyPlot->setAxisScaleDraw(QwtPlot::xBottom, new DaysScaleDraw());
QFont weeklyPlotAxisFont = weeklyPlot->axisFont(QwtPlot::yLeft);
weeklyPlot->setAxisVisible(QwtAxis::YRight, true);
weeklyPlot->setAxisMaxMinor(QwtAxis::XBottom,0);
weeklyPlot->setAxisScaleDraw(QwtAxis::XBottom, new DaysScaleDraw());
QFont weeklyPlotAxisFont = weeklyPlot->axisFont(QwtAxis::YLeft);
weeklyPlotAxisFont.setPointSize(weeklyPlotAxisFont.pointSize() * 0.9f);
weeklyPlot->setAxisFont(QwtPlot::xBottom, weeklyPlotAxisFont);
weeklyPlot->setAxisFont(QwtPlot::yLeft, weeklyPlotAxisFont);
weeklyPlot->setAxisFont(QwtPlot::yRight, weeklyPlotAxisFont);
weeklyPlot->setAxisFont(QwtAxis::XBottom, weeklyPlotAxisFont);
weeklyPlot->setAxisFont(QwtAxis::YLeft, weeklyPlotAxisFont);
weeklyPlot->setAxisFont(QwtAxis::YRight, weeklyPlotAxisFont);
weeklyPlot->canvas()->setFrameStyle(QFrame::NoFrame);
weeklyPlot->setCanvasBackground(Qt::white);
@@ -70,18 +70,18 @@ WeeklySummaryWindow::WeeklySummaryWindow(bool useMetricUnits,
weeklyDurationCurve->setBrush(QColor(255,200,0,255));
weeklyDurationCurve->setRenderHint(QwtPlotItem::RenderAntialiased);
weeklyDurationCurve->setCurveAttribute(QwtPlotCurve::Inverted, true); // inverted, right-to-left
weeklyDurationCurve->setYAxis(QwtPlot::yRight);
weeklyDurationCurve->setYAxis(QwtAxis::YRight);
weeklyDurationCurve->attach(weeklyPlot);
// set up the weekly bike score plot:
weeklyBSPlot = new QwtPlot();
weeklyBSPlot->enableAxis(QwtPlot::yRight, true);
weeklyBSPlot->setAxisMaxMinor(QwtPlot::xBottom,0);
weeklyBSPlot->setAxisScaleDraw(QwtPlot::xBottom, new DaysScaleDraw());
weeklyBSPlot->setAxisVisible(QwtAxis::YRight, true);
weeklyBSPlot->setAxisMaxMinor(QwtAxis::XBottom,0);
weeklyBSPlot->setAxisScaleDraw(QwtAxis::XBottom, new DaysScaleDraw());
QwtText textLabel = QwtText();
weeklyBSPlot->setAxisFont(QwtPlot::xBottom, weeklyPlotAxisFont);
weeklyBSPlot->setAxisFont(QwtPlot::yLeft, weeklyPlotAxisFont);
weeklyBSPlot->setAxisFont(QwtPlot::yRight, weeklyPlotAxisFont);
weeklyBSPlot->setAxisFont(QwtAxis::XBottom, weeklyPlotAxisFont);
weeklyBSPlot->setAxisFont(QwtAxis::YLeft, weeklyPlotAxisFont);
weeklyBSPlot->setAxisFont(QwtAxis::YRight, weeklyPlotAxisFont);
weeklyBSPlot->canvas()->setFrameStyle(QFrame::NoFrame);
weeklyBSPlot->setCanvasBackground(Qt::white);
@@ -99,7 +99,7 @@ WeeklySummaryWindow::WeeklySummaryWindow(bool useMetricUnits,
weeklyRICurve->setBrush(Qt::green);
weeklyRICurve->setRenderHint(QwtPlotItem::RenderAntialiased);
weeklyRICurve->setCurveAttribute(QwtPlotCurve::Inverted, true); // inverted, right-to-left
weeklyRICurve->setYAxis(QwtPlot::yRight);
weeklyRICurve->setYAxis(QwtAxis::YRight);
weeklyRICurve->attach(weeklyBSPlot);
// set baseline curves to obscure linewidth variations along baseline
@@ -342,13 +342,13 @@ WeeklySummaryWindow::refresh()
weeklyPlotAxisTitleFont.setPointSize(10);
weeklyPlotAxisTitleFont.setBold(true);
textLabel.setFont(weeklyPlotAxisTitleFont);
weeklyPlot->setAxisTitle(QwtPlot::yLeft, textLabel);
weeklyPlot->setAxisTitle(QwtAxis::YLeft, textLabel);
textLabel.setText("Minutes");
weeklyPlot->setAxisTitle(QwtPlot::yRight, textLabel);
weeklyPlot->setAxisTitle(QwtAxis::YRight, textLabel);
textLabel.setText(useBikeScore ? "BikeScore" : "kJoules");
weeklyBSPlot->setAxisTitle(QwtPlot::yLeft, textLabel);
weeklyBSPlot->setAxisTitle(QwtAxis::YLeft, textLabel);
textLabel.setText(useBikeScore ? "Intensity" : "xPower");
weeklyBSPlot->setAxisTitle(QwtPlot::yRight, textLabel);
weeklyBSPlot->setAxisTitle(QwtAxis::YRight, textLabel);
// for the daily distance/duration and bikescore plots:
// first point: establish zero position
@@ -428,18 +428,18 @@ WeeklySummaryWindow::refresh()
// Distance/Duration plot:
weeklyDistCurve->setData(xdist, ydist, 16);
weeklyPlot->setAxisScale(QwtPlot::yLeft, 0, weeklyDistCurve->maxYValue()*1.1, 0);
weeklyPlot->setAxisScale(QwtPlot::xBottom, 0.5, 7.5, 0);
weeklyPlot->setAxisTitle(QwtPlot::yLeft, useMetricUnits ? "Kilometers" : "Miles");
weeklyPlot->setAxisScale(QwtAxis::YLeft, 0, weeklyDistCurve->maxYValue()*1.1, 0);
weeklyPlot->setAxisScale(QwtAxis::XBottom, 0.5, 7.5, 0);
weeklyPlot->setAxisTitle(QwtAxis::YLeft, useMetricUnits ? "Kilometers" : "Miles");
weeklyDurationCurve->setData(xdur, ydur, 16);
weeklyPlot->setAxisScale(QwtPlot::yRight, 0, weeklyDurationCurve->maxYValue()*1.1, 0);
weeklyPlot->setAxisScale(QwtAxis::YRight, 0, weeklyDurationCurve->maxYValue()*1.1, 0);
weeklyPlot->replot();
// BikeScore/Relative Intensity plot
weeklyBSCurve->setData(xbsorw, ybsorw, 16);
weeklyBSPlot->setAxisScale(QwtPlot::yLeft, 0, weeklyBSCurve->maxYValue()*1.1, 0);
weeklyBSPlot->setAxisScale(QwtPlot::xBottom, 0.5, 7.5, 0);
weeklyBSPlot->setAxisScale(QwtAxis::YLeft, 0, weeklyBSCurve->maxYValue()*1.1, 0);
weeklyBSPlot->setAxisScale(QwtAxis::XBottom, 0.5, 7.5, 0);
// set axis minimum for relative intensity
double RImin = -1;
@@ -454,7 +454,7 @@ WeeklySummaryWindow::refresh()
yriorxp[i] = RImin;
weeklyRICurve->setBaseline(RImin);
weeklyRICurve->setData(xriorxp, yriorxp, 16);
weeklyBSPlot->setAxisScale(QwtPlot::yRight, RImin, weeklyRICurve->maxYValue()*1.1, 0);
weeklyBSPlot->setAxisScale(QwtAxis::YRight, RImin, weeklyRICurve->maxYValue()*1.1, 0);
weeklyBSPlot->replot();

BIN
doc/user/govss.pdf Normal file

Binary file not shown.

BIN
doc/user/swimscore.pdf Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 KiB

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
doc/wiki/Athlete_Gear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 671 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
doc/wiki/ImagesImport.mp4 Normal file

Binary file not shown.

BIN
doc/wiki/ImagesStorage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Some files were not shown because too many files have changed in this diff Show More