Compare commits

...

423 Commits

Author SHA1 Message Date
Alejandro Martinez
d69412d3cc Trigger v3.7-DEV2412 builds
[publish binaries]
2024-12-14 10:25:07 -03:00
Alejandro Martinez
9f54c83bf8 Update translation files based on #4578 2024-12-10 10:17:52 -03:00
Joachim Kohlhammer
80ba6ea06a Reworked the Options-Dialog (#4578)
* Created a new class ActionButtonBox, similar to QDialogButtonBox to
  reduce code duplication when adding footers (add/delete, up/down) to
  QTreeWidgets
* Created a new QStyledItemDelegate for inline editing of lists
* Highlighting the current category (General, Appearance, ...)
* Using the same reset button for Appearance and Measures that is hidden
  in all other categories
* Using the same style and behaviour as in athlete settings for all
  QTreeWidgets
* Using QFormLayout as much as possible, introducing additional support
  for the setting Mac styled Forms

* General: Reordered the settings, grouped them and added a (optional)
  scrollbar
* Data Fields
  * Fields
    * Enabled inline editing
    * Added autocompletion to Screen Tab
    * Added a uniqueness validator to Field
    * Added the list-delegate to Values
  * Colour Keywords: Added the list-delegate to Related Notres Words
  * Defaults: Added autocompletion to Field and Linked field
* Metrics
  * Swapped the tab order
  * Favourites
    * Made the lists wider
    * Moved the up-/down-buttons below the Favourites list
* Training
  * Swapped the tab order of Preferences and Train Devices
  * Remote Controls
    * Switched to inline editing
    * Made the Action non-editable
  * Virtual Bicycle Specifications: Redesigned the dialog
2024-12-09 19:46:35 -03:00
Alejandro Martinez
2505c55f94 Add Device Wizard - Avoid crash on user nonsense
Trying to create a custom virtual power curve
with less than 2 points leads to a crash when
saving device config on terminate.
Reported at the users forum.
2024-12-08 17:57:10 -03:00
Alejandro Martinez
2a2eafe926 Python API - Add deleteXDataSeries and deleteXData
For completeness as requested in the users forum:
GC.deleteXDataSeries(xdata, series) to remove existing XData series
GC.deleteXData(xdata) to remove existing XData
They invoke the corresponding RideFileCommand methods.
2024-12-06 15:31:27 -03:00
Joachim Kohlhammer
000a76983d "Automated only"-flagging for DataProcessors
* Options > Data Fields > Processors & Automation (renamed from
  "Processing")
  * Modernized the UI
  * Added UI to set Automation (None, On Import, On Save) for all
    processors
  * Added UI to set Automated execution only for all processors
  * Showing the processors description
  * Showing the processors setting (if available) in a more userfriendly
    way
  * Added option to add / delete / edit custom Python processors
  * Enabled editing of Python processors via double click
  * Added option to hide code processors
* Removed the submenu to manage Python Fixes from the Edit-menu
* Renamed the Edit-menu to "Process"
* Hiding "automated only"-processors from Process-menu and
  Batchprocessing-dialog
* DataProcessors
  * Turned configuration of all core processors into forms
  * Changed the technical name of all core processors to match their
    classname
  * Added legacy technical name to all core processors to support existing
    scripts
  * Moved description from config-class to DataProcessor
  * Implemented a migration path for existing persisted processor
    configurations
* GSettings
  * Added method to remove settings by key
2024-11-26 20:04:33 -03:00
Alejandro Martinez
c40257911d Update German translation
Contributed by Marcen at the users forum.
2024-11-24 16:31:30 -03:00
Alejandro Martinez
9c1386ad75 Add Swim Stroke metric for lap swims
It can take the following values:
0 - rest, 1 - free, 2 - back, 3 - breast, 4 - fly, 5 - drill, 6 - mixed
When stroke type is not available it evaluates to -1 - na
Type is Peak, which is not exactly right, but we need to refactor
aggregation to fix this (#4575) and this is mostly intended to be
used for intervals, so it is not that relevant anyway.
The text value of this metric is used as the second colum for the Overview chart
in default Swim perspective.
Fixes #4570
2024-11-22 21:34:43 -03:00
Alejandro Martinez
3013e51c8e Fix previous commit (04cb57b)
Shorter than minRest lengths were removed,
but next length duration was not updated.
- Move the update block inside the transaction scope
- Account for removed rows on row index
- Consider column offset due to time and distance
2024-11-21 17:56:30 -03:00
Alejandro Martinez
04cb57bda3 Fix Lap Swims - Ignore lengths shorter than Min Rest
This adds a minimum rest parameter to Fix Lap Swims DP to
ignore lengths shorter than a configured minimum value,
the corresponding time is added to the next length where it
is assumed to belong.
Minimum rest length default value is 3 secs, but it can be
changed in DP config.
Test files contributed by Jean Div at the users forum.
Fixes #4571
2024-11-20 19:40:15 -03:00
Alejandro Martinez
3570e089b4 Overview - Fix QColorDialog "Cancel" clicked issue
Contributed by https://github.com/ZajtiM
Fixes #4573
2024-11-20 17:33:58 -03:00
Alejandro Martinez
57c6e6485f Fix Lap Swims - Consecutive rest lenghts
Some devices generate consecutive rest lengths and they
should be included in the same interval, to achive this
we use the change of length distance to mark intervals
instead of just the presence of a rest length as we did
before assuming only one will be generated.
Related to #4571
2024-11-20 17:28:58 -03:00
jgpallero
251dd4d611 Update Spanish translation (#4569) 2024-11-05 08:34:38 -03:00
Alejandro Martinez
5bbb79e7ba Update snapshot builds
Summary of changes from v3.7-dev2410:
9a269677d Settings: Inline-editing for Measures (#4567)
928891634 Update Spanish translation (#4566, #4563)
e3fb6c4e3 AutoCP: Proposing new ranges only for younger estimates (#4565)
6576b12a7 Infowidget: Made more strings translatable (#4564)
c86b5a6be Harmonize the layout of athlete settings (#4562)
[publish binaries]
2024-11-04 17:17:08 -03:00
Peret
fab2d35300 util/antlog.py migrated to python3 (#4568)
Simplified code, no longer compatible with python2
[skip ci]
2024-11-04 13:56:16 -03:00
Joachim Kohlhammer
eaa86779e5 Implemented precalulation of sizeHint
For the following classes:
* ComboBoxDelegate
* DateEditDelegate
* TimeEditDelegate
* SpinBoxEditDelegate
2024-11-04 09:14:12 -03:00
Joachim Kohlhammer
ef3b8acfb4 Precalculating sizeHint for DoubleSpinBoxEditDelegate 2024-11-04 09:14:12 -03:00
Joachim Kohlhammer
9a269677d8 Settings: Inline-editing for Measures
* Implmented inline-editing in Measures-tab, similar to Zones (Power,
  HR, Pace)
* Disabled editing of columns Datetime, Source, Original-Source
2024-11-04 09:14:12 -03:00
jgpallero
928891634b Update Spanish translation (#4566) 2024-11-01 19:41:55 -03:00
Joachim Kohlhammer
e3fb6c4e30 AutoCP: Proposing new ranges only for younger estimates (#4565)
* Only proposing a new range if the current estimate starts after the
  current range (otherwise deviations should be handled by review)
* Review-dialog: Replaced the relation-signs (<>) by arrows (↗↘) for
  better readability
2024-11-01 19:41:24 -03:00
Joachim Kohlhammer
6576b12a7f Infowidget: Made more strings translatable (#4564)
* Made more strings in InfoWidget translatable
* Updated the translation files
2024-10-31 18:58:33 -03:00
Joachim Kohlhammer
c86b5a6be9 Harmonize the layout of athlete settings (#4562)
Settings
* About
  * Show the athletes name
  * Mask the avatar-image as a circle
* Model
  * Add button to revert to defaults
* Auto Import
  * Use inline editing
* Backup
  * Add a "Backup now"-button

Create new athlete
* Rename NewCyclistDialog to NewAthleteWizard and turned it into a
  2-page wizard
* ChooseCyclistDialog: Open the NewAthleteWizard without interaction
  if no athlete is available

Common
* Avatar image
  * Use Qt::SmoothTransformation for improved quality
  * Crop to the center of the original image
  * Keep aspect ratio of the original image
* All forms: Use QFormLayout to simplify the code and provide a
  desktop aware layout
* Switch to QDialogButtonBox for a button order aligned with the
  desktop

Centralized creation of QFormLayouts
* Added option to use either system-style or mac-style for QFormLayouts
2024-10-29 09:49:19 -03:00
jgpallero
f3aedd6184 Update Spanish translation (#4563) 2024-10-27 18:41:01 -03:00
Alejandro Martinez
fa2402f4b2 October 2024 Development Build
[publish binaries]
2024-10-26 11:10:55 -03:00
Joachim Kohlhammer
210cc1a782 Zones: Sorting ranges in reverse (#4561)
Power, Heartrate, Pace: Showing the most recent range at the top instead
of at the bottom by adding a hidden column _rnum to the TreeViews
2024-10-23 18:59:29 -03:00
Joachim Kohlhammer
02548a98aa Refinement of Semi automatic creation for power zones (#4560)
* Renamed "Adopt" to "Review..."
* Replaced "adopt" by "review" in the code
* Fixed crash when using CP for FTP
2024-10-22 13:26:09 -03:00
Paul Johnson
2a77a639f9 Editable metadata tile fixes #4559
Fixed expanding cancel and ok buttons
Set minimum width for the different fields types
2024-10-21 20:03:02 -03:00
Paul Johnson
cb2198ab74 Position tile config menu (#4558)
* Move tile config dialog near the cog icon
* Ensure config dialog remains within GC window
2024-10-20 17:18:19 -03:00
Paul Johnson
8aea1cfed6 Editable metadata tile (#4519)
* New edit icon on metadata tiles that have editable content
* New metadata dialog
* Ensure metadata dialog remains within GC window
2024-10-20 15:02:30 -03:00
Alejandro Martinez
5c694d0f45 Adapt CloudServiceSyncDialog with service capabilities
Some Cloud Services s.t. Nolio doesn't offer (yet) upload,
but upload was always presented.
Fixes #4177
2024-10-19 09:29:29 -03:00
Alejandro Martinez
3d3aed8eca Table tile in Overview - Colorize for scalar data
Copied how it works for multirow data
Fixes #4062
2024-10-18 13:05:39 -03:00
Joachim Kohlhammer
a5829c5c13 Semi automatic creation of ranges for power zones (#4543)
* Changed the UI of CPPage to inline-editing of all values in all tables
* Added a sports-specific selector for the model (cp2, cp3, ext, manual)
* Allowed to create new ranges either manually or based on the estimated
  values of the model
* Added option to reset each ranges values to those of the selected
  model
* Added message to create a new range if todays estimate differs from
  those of the currently active one
* Refined semi automatic power zones
* Added a dialog to inspect and accept only some values while adoption
* Added info messages
  * when the model does not provide FTP or PMAX
  * that AeTP is only a very rough estimate
* Added a tolerance in comparison before proposing new values
* Using the following order for defaults when adding a new manual range
  * selected row
  * last row
  * predefined defaults
* Zones-Tab: To prevent crashes, a message is shown instead of the real
  interface if a metric refresh is ongoing
* Changed Pace- and HR-Tabs to use inline editing
* Moved the unittests into the same structure as the sourcecode
* Added a simple (incomplete) unittest for kphToPace
* Improved setting the column width
* En-/Disabling the action buttons (add, delete, ...) based on the
  contents state
* Changed the layout to prevent jumping widgets when showing / hiding
  buttons
* Fixed compiler warnings from Visual-C++
* Adopt dialog: Refined layout
* Fixed the unit of "From BPM" on HR-Page
* Set the default mode to manual
Fixes #1381
2024-10-17 18:12:15 -03:00
Alejandro Martinez
d6e570ce3c Update snapshot builds
Relevant changes from v3.7-DEV2408
a30b96cc8 Refactored the placement of items in the ChartSpace (#4549)
62ef8abe4 Make the Workout Editor's Settings Persistent (#4553)
217bd3b88 Scale Line Width default values (#4556)
f4d6c2ae4 avoid regression caused by #4337 due to changed order of data series enum
61fa77b2c respect linewidth setting inside the workout editor realtime plot (#4550)
51b0c9099 Fix intervals in Compare Pane are 1 sample short
b62a2d319 Ride Cache - Don't remove 1 sec intervals
c51941231 CP chart - show tooltip for model curve
5f1598c43 FIT - map fields to standard only for record msg (#4521)
9242f724d Implemented user defined relative date ranges (#4534)
60f903361 Cycling dynamics in train mode (#4337)
1230dc7c6 FIT parser - Lap messages can be first (#4535)
79b523781 Removed wildcard from translatable part (#4545)
ee992ad13 Enable Performance Tests for CV charts
7e7ffd3cb Aerolab - fix imperial units labels (#4542)
[publish binaries]
2024-10-13 18:44:44 -03:00
Joachim Kohlhammer
a30b96cc8a Refactored the placement of items in the ChartSpace (#4549)
Fixes #4467:
* Tiles are dragged to a column, inserted into the columns tile order
* Placing tiles left or right of the existing columns creates a new
  column (up to a fixed limit)
* As there is no concept of lines, the placement must
  * always respect the users choice of a column
  * never move a tile horizontally without user interaction
* Shift-resizing a tile allows spanning multiple columns
* Improved change detection
* Preventing superfluous layouting requests and order increments
* Added a visual indicator where the item will be placed when dropped
* Fixed a glitch when creating new columns on the right, when dragging
  beyond a newly created column on the right, the visual indicator was
  hidden and pseudo changes where detected.
2024-10-13 18:33:08 -03:00
Thies Lennart Alff
62ef8abe42 Make the Workout Editor's Settings Persistent (#4553)
store the workout editor's chart settings as properties of the
perspective's layout xml.
2024-10-13 17:36:01 -03:00
Alejandro Martinez
217bd3b888 Scale Line Width default values (#4556)
This is a follow up of a discussion in #4550: since configurable
GC_LINEWIDTH is not scaled on use, it is convenient to scale fixed
default values so they adapt to display configuration on first use,
to make easier the initial setup for new users without affecting existing ones.
2024-10-13 16:19:09 -03:00
Thies Lennart Alff
f4d6c2ae40 avoid regression caused by #4337 due to changed order of data series
enum
2024-10-13 13:43:33 -03:00
Alejandro Martinez
6e039be362 Revert "sort the dial window's combobox by name (#4551)"
This reverts commit 47e94000a5.
Fixes #4554
2024-10-13 13:41:49 -03:00
Thies Lennart Alff
47e94000a5 sort the dial window's combobox by name (#4551) 2024-10-12 08:34:35 -03:00
Thies Lennart Alff
61fa77b2c0 respect linewidth setting inside the workout editor realtime plot (#4550) 2024-10-11 19:16:08 -03:00
Alejandro Martinez
51b0c9099a Fix intervals in Compare Pane are 1 sample short
The fake rides created for intervals in Compare Pane don't include
the last sample, so they are 1 sample short and 1 sec intervals
don't appear. WPrime calculations are avoided when the ride has
only 1 sample to avoid crashes, besides it doesn't make any sense.
Fixes #4552
2024-10-11 11:18:44 -03:00
Alejandro Martinez
b62a2d3190 Ride Cache - Don't remove 1 sec intervals
Previous behaviour was weird: 1 sec intervals could be created and displayed,
but they were discarded on activity save.
Also 1 sec intervals are useful for 3 param model fitting.
2024-10-04 10:47:52 -03:00
Alejandro Martinez
c519412311 CP chart - show tooltip for model curve
It is useful to see predicted values.
2024-10-04 10:46:52 -03:00
Alejandro Martinez
412c995a43 Update snapshot builds
Relevant changes from v3.7-DEV2408
5f1598c43 FIT - map fields to standard only for record msg (#4521)
9242f724d Implemented user defined relative date ranges (#4534)
60f903361 Cycling dynamics in train mode (#4337)
1230dc7c6 FIT parser - Lap messages can be first (#4535)
79b523781 Removed wildcard from translatable part (#4545)
ee992ad13 Enable Performance Tests for CV charts
7e7ffd3cb Aerolab - fix imperial units labels (#4542)
[publish binaries]
2024-09-28 17:33:46 -03:00
Alejandro Martinez
5f1598c437 FIT - map fields to standard only for record msg
Fixes #4521
2024-09-28 13:17:46 -03:00
Joachim Kohlhammer
9242f724db Implemented user defined relative date ranges (#4534)
Fixes #4512
* Added additional time range options for user defined seasons
  * Relative start (e.g. 3 months ago)
  * Duration after start / Duration before end (e.g. 2 months)
  * Year to Date end, defining the end as the closest day with todays
    day and month after start
* Refactored Season.h/cpp and SeasonParser.h/cpp for better testability
  * Kept Season, Phase, SeasonEvent, SeasonOffset, SeasonLength in
    Season.h/cpp
  * Moved all UI related classes to SeasonDialogs.h/cpp
  * Renamed SeasonParser.h/cpp to Seasons.h/cpp, moved class Seasons
    there
* Replaced deprecated Qt classes
  * Replaced QRegExp by QRegularExpression in SeasonParser
  * Rewrote parsing seasons.xml to use QXmlStreamReader instead of
    QXmlSimpleReader
* Unittesting
  * Added a simple way to implement and execute (make check) unittests
    in Golden Cheetahs source tree based on Qt Test
    (https://doc.qt.io/qt-6/qttest-index.html), tested on Linux and
    Windows
  * Implemented unittests for classes (mostly before refactoring)
    * Season
    * SeasonParser
    * SeasonOffset
2024-09-27 11:25:03 -03:00
vlcvboyer
60f9033617 Cycling dynamics in train mode (#4337)
* TRAIN - add cycling dynamics
Power sensors which deliver cycling dynamics such as power start angle,
rider position, etc. are supported during hometrainer session.
Goldencheetah requests power sensor capabilities and, when available,
request the sensor to enable them (power phase, pedal position, etc.
and 8Hz transmission mode which is mandatory when accessing those
additional data pages)

* COSMETIC - FIX comment related to gc csv header
The comment was not reflecting the up-to-date file
content as per latest CSV header

* FIX load/slope in CSV
Only target power was recorded in CSV records during hometrainer
session.
When not using ERG mode but slope mode then the data was lost.
This patch take care of training mode to determine which data
is to be recorded.

* TRAIN - flexible gc CSV
Allows to add fields in CSV file recorded during hometrainer session
without impacting a lot of files in the code
Historical first fields are still used to determine taht this file
has been created by GoldenCheetah.
During CSV parsing GoldenCheetah will use CSV header to determine which
fields are part of the file and to locate the column which contain it

* TRAIN - add cycling dynamics to CSV records
during hometrainer session


* CsvRideFile fixes
Free gcSeries and Qt6 compatibility
---------

Co-authored-by: Alejandro Martinez <amtriathlon@gmail.com>
2024-09-26 17:21:50 -03:00
Michal Powalko
76e8a07f59 Add Morpheus M7 heart rate monitor
Adds the heart rate monitor from Morpheus Training System:

https://trainwithmorpheus.com/
https://trainwithmorpheus.com/m7-user-guide/
2024-09-26 17:16:00 -03:00
Alejandro Martinez
1230dc7c68 FIT parser - Lap messages can be first
in the new file structure, like in the companion
test file from a Sigma ROX 11.1
2024-09-21 15:29:02 -03:00
Joachim Kohlhammer
79b523781d Removed wildcard from translatable part
Some translations (de, sv) for filters used in QFileDialgos contained
commas to separate wildcards. As this is in violation with Qts syntax,
the dialogs didn't show any files.

This commit separates the wildcards from the name of the filter so that
only the name can be manipulated by translation. All affected
translations are updated.
2024-09-21 12:10:25 -03:00
Alejandro Martinez
85ee81371a Tidy up previous commit 2024-09-20 10:10:13 -03:00
Alejandro Martinez
ee992ad130 Enable Performance Tests for CV charts
Show them in CV charts and use them for fitting,
just like they work in CP charts.
2024-09-19 21:27:51 -03:00
Alejandro Martinez
7e7ffd3cba Aerolab - fix imperial units labels
Fixes #4542
2024-09-13 19:45:24 -03:00
Alejandro Martinez
7536ecdad2 Update Issue Template
[skip ci]
Let's make it simpler and more explicit in another attempt
to prevent users from creating issues unnecessarily.
2024-09-12 10:29:10 -03:00
Alejandro Martinez
0eddf7ab27 Update Issue Template
[skip ci]
Let's make it simpler and more explicit in another attempt
to prevent users from creating issues unnecessarily.
2024-09-12 10:25:42 -03:00
Alejandro Martinez
c8bc647ab3 Update Issue Template
[skip ci]
Let's make it simpler and more explicit in another attempt
to prevent users from creating issues unnecessarily.
2024-09-12 10:23:12 -03:00
Alejandro Martinez
1f62951b32 Update Issue Template
[skip ci]
Let's make it simpler and more explicit in another attempt
to prevent users from creating issues unnecessarily.
2024-09-12 10:09:35 -03:00
Alejandro Martinez
c0bf155398 Update snapshot builds
This is the same as 2404 dev build with a fix
to import FIT files with Power Phase metrics.
Some XData series were discared before (#4535)
[publish binaries]
2024-09-01 17:05:34 -03:00
Poncho
8ec8f2aaf4 Update FIT SDK definitions to 21.141 2024-08-31 10:34:35 -03:00
Poncho
7971bec15c util/fit/nongarmin.json: add Favero Assioma Pro MX 2024-08-31 10:34:35 -03:00
Alejandro Martinez
ed4d8083db Fix FIT parsing when field scale is not integer
Fixes #4535
2024-08-29 13:33:22 -03:00
Alejandro Martinez
71e3928bc6 Allow GPX files without timestamps as workouts
Fixes #4532
2024-08-18 10:09:15 -03:00
Joachim Kohlhammer
e7e8ef3055 Refined the grammar for filtering workouts (#4531)
* Added support to filter for numbers in the description / title / tags,
  similar to #4529
* Added quoted strings when filtering in description / title / tags:
  * Words can be grouped by putting them in quotes to search for exact
    matches
  * Keywords can be put in quotes to strip their special meaning
  * Examples: "Power Builder 60", "Power" 60
  * Added this also to TrainerDay, keeping the syntax similar
* Adjusted the autocompletion to not propose keywords when within open
  quotes
2024-08-08 18:42:38 -03:00
Alejandro Martinez
e783586ec3 Update Issue Template
[skip ci]
2024-08-07 18:17:51 -03:00
Joachim Kohlhammer
06b0ea5a81 TrainerDay: Setting the geometry of the dialog
Setting the geometriy of the download dialog instead of the minimum
size, thus allowing full resizing.
See https://groups.google.com/g/golden-cheetah-users/c/Xi6d3L1t9QA/m/gWe2Q2uNAQAJ
2024-08-05 16:11:05 -03:00
Joachim Kohlhammer
9ea6949f13 TrainerDay: Allowing numbers in query for workouts
See https://groups.google.com/g/golden-cheetah-users/c/Xi6d3L1t9QA/m/gWe2Q2uNAQAJ
2024-08-05 16:11:05 -03:00
Joachim Kohlhammer
a17d069202 TrainerDay: Set fallback for max workouts per page
See https://github.com/GoldenCheetah/GoldenCheetah/pull/4522#issuecomment-2253027635
2024-08-05 16:11:05 -03:00
Alejandro Martinez
46bf477675 Revert force version string on non-tagged ci builds
[skip ci]
2024-08-04 12:18:03 -03:00
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
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
1521 changed files with 197311 additions and 141816 deletions

6
.gitignore vendored
View File

@@ -14,6 +14,8 @@ Makefile
*.swp
*.user
*.AppImage
*.tab.c
*.tab.h
# osx noise
.DS_Store
@@ -29,6 +31,7 @@ xcshareddata/
moc_*
moc/
.moc
obj/
lib/
bin/
@@ -58,3 +61,6 @@ build.pro.user
build.pro.user.*
doc/contrib/WASP Packet Protocol.pdf
# Qt testlib
target_wrapper.sh

View File

@@ -42,14 +42,18 @@ env:
- 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
@@ -112,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:
@@ -205,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,36 +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 and
minimum bison version is 2.7, both can be installed using Homebrew.
Ale Martinez - Oct, 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
@@ -41,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
@@ -76,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
-----------------------
@@ -93,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'.
@@ -107,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)
---------------------------------------------------------------------
@@ -182,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
@@ -223,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:
@@ -250,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,10 +1,5 @@
Issue tracker is **only** for Bugs and Features, please don't open issues for questions or technical support. Before to open a new issue please read the contributing guidelines (link below).
If you need help, technical support or want to ask questions or give feedback, please use users/developers forums:
- Users - https://groups.google.com/forum/#!forum/golden-cheetah-users
- Developers - https://groups.google.com/forum/#!forum/golden-cheetah-developers
If you have questions, please read the FAQs and User's/Developer's Guide:
* FAQs - https://github.com/GoldenCheetah/GoldenCheetah/wiki/FAQ
* User's Guide - https://github.com/GoldenCheetah/GoldenCheetah/wiki/UG_Main-Page_Users-Guide
* Developer's Guide - https://github.com/GoldenCheetah/GoldenCheetah/wiki/Developers-guide
If you need help or technical support please use the forums:
* Users - https://groups.google.com/forum/#!forum/golden-cheetah-users
* Developers - https://groups.google.com/forum/#!forum/golden-cheetah-developers
Issue tracker is **only** for previously discussed Bugs and Features, others will be closed without discussion.

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:
@@ -43,6 +42,8 @@ environment:
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
@@ -63,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
@@ -115,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
@@ -134,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
@@ -151,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
@@ -161,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
@@ -192,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 }
@@ -205,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

@@ -1,4 +1,5 @@
TEMPLATE = subdirs
SUBDIRS = qwt
SUBDIRS += src
SUBDIRS += unittests
CONFIG += ordered

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

@@ -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();

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 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.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

12
qwt/.gitignore vendored Normal file
View File

@@ -0,0 +1,12 @@
Makefile
.qmake.stash
obj
moc
rcc
lib
bin
html
plugins
resources
Doxygen.log
*.swp

View File

@@ -1,38 +0,0 @@
Qwt TODO list
Ideas
------
- Improve Documention
- QAbstractModel -> QwtSeriesData
- Box/Whisker plot item
- QwtSeriesData + functors
- QwtSeriesData/QwtPlotCurve + Level of details (Douglas Peucker)
- Common zoom stack for all navigation objects
- Watermark Item
- Contour algorithm for vectors: http://apptree.net/conrec.htm
- QwtPlotCanvas rendered via FBO, PBO
- Time/Date scale engine
- TeX texts
- Grid of QwtPlots
- Interval scale labels ( between 2 ticks )
- More than 4 axes
- QwtIntervalSymbol + QPainterPath/...
- QwtPlotScene + breaking composite architecture
- Using QStaticText for markers ( and scales ? )
- Scales/Grid item like in QwtPolarGrid
- Container for a 2D matrix
- Waterfall plots
- transform/invTransform for polygons and lines
- cursor item
- line marker with a line from the position to the axis
- quadtree
- QwtText supporting Qt::TextElideMode
- Multitouch events
- QwtKnob/QwtDial fixed contents size mode
- controls ( f.e QwtWheel ) with a very dark palette
Bugs/Change requests
--------------------
- Remove QwtScaleTransformation::copy()
- Reference value for QwtThermo
- Transparent canvas background + backingstore

View File

@@ -1,8 +1,8 @@
#! /bin/sh
#
# Generates a Qwt package from sourceforge svn
# Generates a Qwt package from the sourceforge repository
#
# Usage: svn2package.sh [-b|--branch <svn-branch>] [packagename]
# Usage: 2package.sh.sh [-b|--branch <branch>] [packagename]
#
##########################
@@ -10,15 +10,15 @@
##########################
function usage() {
echo "Usage: $0 [-b|--branch <svn-branch>] [-s|--suffix <suffix>] [-html] [-pdf] [-qch] [packagename]"
echo "Usage: $0 [-b|--branch <branch>] [-s|--suffix <suffix>] [-html] [-pdf] [-qch] [packagename]"
exit 1
}
################################
# checkout
# downloadQwt
################################
function checkoutQwt() {
function downloadQwt() {
if [ -x $2 ]
then
@@ -29,18 +29,14 @@ function checkoutQwt() {
fi
fi
svn -q co https://svn.code.sf.net/p/qwt/code/$1/$2
git clone -b $1 git://git.code.sf.net/p/qwt/git $2
if [ $? -ne 0 ]
then
echo "Can't access sourceforge SVN"
echo "Can't access sourceforge repository"
exit $?
fi
if [ "$3" != "$2" ]
then
rm -rf $3
mv $2 $3
fi
rm -rf $2/.git $2/.gitignore
}
##########################
@@ -55,8 +51,6 @@ function cleanQwt {
exit $?
fi
find . -name .svn -print | xargs rm -r
rm -f TODO
rm -rf admin
rm -rf doc/tex
@@ -86,10 +80,10 @@ function cleanQwt {
if [ "$SUFFIX" != "" ]
then
sed -i -e "s/\$\$QWT_VERSION-svn/\$\$QWT_VERSION-$SUFFIX/" qwtconfig.pri
sed -i -e "s/\$\$QWT_VERSION-dev/\$\$QWT_VERSION-$SUFFIX/" qwtconfig.pri
sed -i -e "s/\$(QWTVERSION)/$VERSION-$SUFFIX/" doc/install.dox
else
sed -i -e "s/\$\$QWT_VERSION-svn/\$\$QWT_VERSION/" qwtconfig.pri
sed -i -e "s/\$\$QWT_VERSION-dev/\$\$QWT_VERSION/" qwtconfig.pri
sed -i -e "s/\$(QWTVERSION)/$VERSION/" doc/install.dox
fi
@@ -234,8 +228,7 @@ function prepare4Unix {
##########################
QWTDIR=
SVNDIR=trunk
BRANCH=qwt
BRANCH=multiaxes
SUFFIX=
VERSION=
GENERATE_DOC=0
@@ -248,7 +241,7 @@ while [ $# -gt 0 ] ; do
-h|--help)
usage; exit 1 ;;
-b|--branch)
shift; SVNDIR=branches; BRANCH=$1; shift;;
shift; BRANCH=$1; shift;;
-s|--suffix)
shift; SUFFIX=$1; shift;;
-html)
@@ -276,8 +269,8 @@ fi
TMPDIR=/tmp/$QWTDIR-tmp
echo -n "checkout to $TMPDIR ... "
checkoutQwt $SVNDIR $BRANCH $TMPDIR
echo -n "downloading to $TMPDIR ... "
downloadQwt $BRANCH $TMPDIR
cleanQwt $TMPDIR
echo done

View File

@@ -0,0 +1 @@
#include "qwt_abstract_legend.h"

View File

@@ -0,0 +1 @@
#include "qwt_abstract_scale.h"

View File

@@ -0,0 +1 @@
#include "qwt_abstract_scale_draw.h"

View File

@@ -0,0 +1 @@
#include "qwt_abstract_slider.h"

View File

@@ -0,0 +1 @@
#include "qwt_color_map.h"

View File

@@ -0,0 +1 @@
#include "qwt_analog_clock.h"

View File

@@ -0,0 +1 @@
#include "qwt_arrow_button.h"

View File

@@ -0,0 +1 @@
#include "qwt_axis.h"

View File

@@ -0,0 +1 @@
#include "qwt_axis_id.h"

View File

@@ -0,0 +1 @@
#include "qwt_bezier.h"

View File

@@ -0,0 +1 @@
#include "qwt_point_data.h"

View File

@@ -0,0 +1 @@
#include "qwt_clipper.h"

View File

@@ -0,0 +1 @@
#include "qwt_color_map.h"

View File

@@ -0,0 +1 @@
#include "qwt_column_symbol.h"

View File

@@ -0,0 +1 @@
#include "qwt_column_symbol.h"

View File

@@ -0,0 +1 @@
#include "qwt_compass.h"

View File

@@ -0,0 +1 @@
#include "qwt_dial_needle.h"

View File

@@ -0,0 +1 @@
#include "qwt_compass_rose.h"

View File

@@ -0,0 +1 @@
#include "qwt_compass.h"

View File

@@ -0,0 +1 @@
#include "qwt_dial_needle.h"

View File

@@ -0,0 +1 @@
#include "qwt_counter.h"

View File

@@ -0,0 +1 @@
#include "qwt_curve_fitter.h"

View File

@@ -0,0 +1 @@
#include "qwt_date.h"

View File

@@ -0,0 +1 @@
#include "qwt_date_scale_draw.h"

View File

@@ -0,0 +1 @@
#include "qwt_date_scale_engine.h"

View File

@@ -0,0 +1 @@
#include "qwt_dial.h"

View File

@@ -0,0 +1 @@
#include "qwt_dial_needle.h"

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