Home > matGeom > geom3d > geodesicCylinder.m

geodesicCylinder

PURPOSE ^

GEODESICCYLINDER computes the geodesic between two points on a cylinder.

SYNOPSIS ^

function [geo, geoLength, conGeo, conGeoLength] = geodesicCylinder(pts, cyl, varargin)

DESCRIPTION ^

GEODESICCYLINDER computes the geodesic between two points on a cylinder.

   [GEO, GEOLENGTH] = geodesicCylinder(PTS, CYL) computes the geodesic 
   between the two points PTS projected onto the infinite cylinder CYL.  
   PTS is a 2-by-3 array, and CYL is a 1-by-7 array. Result is the 
   polyline GEO (500-by-3 array) [500 = default] containing the  
   coordinates of the geodesic between two projected points. GEOLENGTH 
   contains the analytical length of the geodesic.

   [~, ~, CONGEO, CONGEOLENGTH] = geodesicCylinder(PTS, CYL) provides the
   conjugate geodesic and its analytical length.

   ... = geodesicCylinder(PTS, CYL, 'n', N) defines the number of points
   representing the geodesic and conjugate geodesic.

   Example
       demoGeodesicCylinder

   See also
     drawCylinder, projPointOnCylinder

   Source
     Based on the script 'geodesic.m' by Lei Wang
     https://mathworks.com/matlabcentral/fileexchange/6522

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [geo, geoLength, conGeo, conGeoLength] = geodesicCylinder(pts, cyl, varargin)
0002 %GEODESICCYLINDER computes the geodesic between two points on a cylinder.
0003 %
0004 %   [GEO, GEOLENGTH] = geodesicCylinder(PTS, CYL) computes the geodesic
0005 %   between the two points PTS projected onto the infinite cylinder CYL.
0006 %   PTS is a 2-by-3 array, and CYL is a 1-by-7 array. Result is the
0007 %   polyline GEO (500-by-3 array) [500 = default] containing the
0008 %   coordinates of the geodesic between two projected points. GEOLENGTH
0009 %   contains the analytical length of the geodesic.
0010 %
0011 %   [~, ~, CONGEO, CONGEOLENGTH] = geodesicCylinder(PTS, CYL) provides the
0012 %   conjugate geodesic and its analytical length.
0013 %
0014 %   ... = geodesicCylinder(PTS, CYL, 'n', N) defines the number of points
0015 %   representing the geodesic and conjugate geodesic.
0016 %
0017 %   Example
0018 %       demoGeodesicCylinder
0019 %
0020 %   See also
0021 %     drawCylinder, projPointOnCylinder
0022 %
0023 %   Source
0024 %     Based on the script 'geodesic.m' by Lei Wang
0025 %     https://mathworks.com/matlabcentral/fileexchange/6522
0026 %
0027 
0028 % ---------
0029 % Author: oqilipo
0030 % Created: 2021-04-17, using R2020b
0031 % Copyright 2021
0032 
0033 parser = inputParser;
0034 addRequired(parser, 'pts', @(x) validateattributes(x, {'numeric'},...
0035     {'size',[2 3],'real','finite','nonnan'}));
0036 addRequired(parser, 'cyl', @(x) validateattributes(x, {'numeric'},...
0037     {'size',[1 7],'real','finite','nonnan'}));
0038 addParameter(parser,'n',500, @(x) validateattributes(x, {'numeric'},...
0039     {'scalar','>', 2,'<=', 1e5}));
0040 parse(parser,pts,cyl,varargin{:});
0041 pts = parser.Results.pts;
0042 cyl = parser.Results.cyl;
0043 n = parser.Results.n;
0044 
0045 % Radius of the cylinder
0046 cylRadius = cyl(7);
0047 
0048 % Project points onto the open (infinite) cylinder
0049 ptProj(1,:) = projPointOnCylinder(pts(1,:), cyl, 'open');
0050 ptProj(2,:) = projPointOnCylinder(pts(2,:), cyl, 'open');
0051 
0052 % Create a transformation for the points into the local cylinder coordinate
0053 % system. Align the cylinder axis with the z axis and translate the
0054 % starting point of the cylinder to the origin.
0055 TFM = createRotationVector3d(cyl(4:6)-cyl(1:3), [0 0 1])*createTranslation3d(-cyl(1:3));
0056 % Transform the points.
0057 ptTfm = transformPoint3d(ptProj, TFM);
0058 % Convert the transformed points to cylindrical coordinates.
0059 [ptsTheta, ptsRadius, ptsHeight] = cart2cyl(ptTfm);
0060 assert(ismembertol(ptsRadius(1),ptsRadius(2)))
0061 assert(ismembertol(ptsRadius(1),cylRadius))
0062 
0063 % Copy thetas for the conjugate geodesic
0064 ptsTheta(:,:,2) = ptsTheta;
0065 ptsTheta(1,1,2) = ptsTheta(1,1,2) + 2*pi;
0066 
0067 geoCyl = nan(n,3,size(ptsTheta,3));
0068 arcLength = nan(1,size(ptsTheta,3));
0069 for t = 1:size(ptsTheta,3)
0070     [geoCyl(:,:,t), arcLength(t)] = geoCurve(ptsTheta(:,:,t), cylRadius, ptsHeight, n);
0071 end
0072 
0073 % Select the shortest geodesic
0074 if arcLength(1) <= arcLength(2)
0075     % Transform the geodesics back to the global coordinate system
0076     geo = transformPoint3d(geoCyl(:,:,1), inv(TFM));
0077     conGeo = transformPoint3d(geoCyl(:,:,2), inv(TFM));
0078     geoLength = arcLength(1);
0079     conGeoLength = arcLength(2);
0080 else
0081     % Transform the geodesics back to the global coordinate system
0082     geo = transformPoint3d(geoCyl(:,:,2), inv(TFM));
0083     conGeo = transformPoint3d(geoCyl(:,:,1), inv(TFM));
0084     geoLength = arcLength(2);
0085     conGeoLength = arcLength(1);
0086 end
0087 
0088 end
0089 
0090 function [geo, arcLength] = geoCurve(theta, r, z, n)
0091 % Parametric expression of the geodesic curve
0092 u = linspace(theta(1),theta(2),n)';
0093 geo(:,1) = r*cos(u);
0094 geo(:,2) = r*sin(u);
0095 geo(:,3) = (z(2)-z(1))/(theta(2)-theta(1))*u + (z(1)*theta(2)-z(2)*theta(1))/(theta(2)-theta(1));
0096 if all(isnan(geo(:,3)))
0097     geo(:,3) = linspace(z(1),z(2),n)';
0098 end
0099 arcLength = sqrt(r^2*(theta(2)-theta(1))^2+(z(2)-z(1))^2);
0100 end

Generated on Wed 16-Feb-2022 15:10:47 by m2html © 2003-2019