├── .gitattributes
├── .gitignore
├── @kml
├── arrow3d.dae
├── camera.m
├── captureScreen.m
├── colorbar.m
├── contour.m
├── contour3.m
├── contourf.m
├── createFolder.m
├── kml.m
├── model.m
├── modelTour.m
├── newAnimation.m
├── newFolder.m
├── overlay.m
├── parseIconURL.m
├── plot.m
├── plot3.m
├── point.m
├── poly.m
├── poly3.m
├── polyMap.m
├── quadoverlay.m
├── quiver.m
├── quiver3d.m
├── scatter.m
├── scatter3.m
├── screenoverlay.m
├── surf.m
├── text.m
└── transfer.m
├── @kmlAnimation
└── kmlAnimation.m
├── README.m
├── html
├── help_clear.jpg
├── help_clear_01.jpg
├── help_clear_02.jpg
├── help_contour.jpg
├── help_contour3.jpg
├── help_contour3_01.jpg
├── help_contour_01.jpg
├── help_kml.jpg
├── help_kml_01.jpg
├── help_model.jpg
├── help_modelTour.jpg
├── help_modelTour_01.jpg
├── help_model_01.jpg
├── help_overlay.jpg
├── help_overlay_01.jpg
├── help_plot.jpg
├── help_plot3.jpg
├── help_plot3_01.jpg
├── help_plot_01.jpg
├── help_point.jpg
├── help_point_01.jpg
├── help_poly.jpg
├── help_poly3.jpg
├── help_poly3_01.jpg
├── help_poly_01.jpg
├── help_quiver.jpg
├── help_quiver3d.jpg
├── help_quiver3d_01.jpg
├── help_quiver_01.jpg
├── help_run.jpg
├── help_run_01.jpg
├── help_scatter.jpg
├── help_scatter3.jpg
├── help_scatter3_01.jpg
├── help_scatter_01.jpg
├── help_text.jpg
├── help_text_01.jpg
├── help_transfer.jpg
├── help_transfer_01.jpg
├── help_transfer_02.jpg
├── help_transfer_03.jpg
├── help_useDegrees.jpg
├── help_useDegrees_01.jpg
├── help_useRadians.jpg
├── help_useRadians_01.jpg
├── helpsearch
│ ├── _t.cfs
│ ├── deletable
│ └── segments
├── helptoc.xml
├── info.xml
├── kml.clear.html
├── kml.contents.html
├── kml.contour.html
├── kml.contour3.html
├── kml.createFolder.html
├── kml.html
├── kml.icons.html
├── kml.model.html
├── kml.modelTour.html
├── kml.overlay.html
├── kml.plot.html
├── kml.plot3.html
├── kml.point.html
├── kml.poly.html
├── kml.poly3.html
├── kml.quiver.html
├── kml.quiver3d.html
├── kml.run.html
├── kml.save.html
├── kml.scatter.html
├── kml.scatter3.html
├── kml.text.html
├── kml.transfer.html
├── kml.useDegrees.html
├── kml.useRadians.html
├── kml.viewKML.html
├── kmldoc.m
├── kmltoolbox.png
├── logo.png
└── nestedFolders.png
├── license.txt
└── test
├── RunTestTour.m
├── RunTests.m
├── RunTestsRadians.m
├── bitslice.m
├── cities.mat
├── logoFEx2.png
└── testAnim.m
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Windows image file caches
2 | Thumbs.db
3 | ehthumbs.db
4 |
5 | # Folder config file
6 | Desktop.ini
7 |
8 | # Recycle Bin used on file shares
9 | $RECYCLE.BIN/
10 |
11 | # Windows Installer files
12 | *.cab
13 | *.msi
14 | *.msm
15 | *.msp
16 |
17 | # =========================
18 | # Operating System Files
19 | # =========================
20 |
21 | # OSX
22 | # =========================
23 |
24 | .DS_Store
25 | .AppleDouble
26 | .LSOverride
27 |
28 | # Icon must ends with two \r.
29 | Icon
30 |
31 | # Thumbnails
32 | ._*
33 |
34 | # Files that might appear on external disk
35 | .Spotlight-V100
36 | .Trashes
37 |
--------------------------------------------------------------------------------
/@kml/camera.m:
--------------------------------------------------------------------------------
1 | function target = camera(this,long,lat,alt,heading,tilt,roll,varargin)
2 | %KML.camera(long,lat,alt) Write a Camera position KML with lat, long, alt,
3 | % heading, tilt, roll
4 | %
5 | % Based on work by Rafael Fernandes de Oliveira (rafael@rafael.aero)
6 | % Original Work: Copyright 2012 Rafael Fernandes de Oliveira
7 | % Author: Thomas Fell (t.r.fell@liv.ac.uk)
8 | % Version: 1.0 $ $Date: 2013/04/18 20:00:00 $
9 |
10 | target = struct('type','','id','');
11 |
12 | [long,lat,heading,tilt,roll] = this.checkUnit(long,lat,heading,tilt,roll);
13 |
14 | p = inputParser;
15 |
16 | nlat = numel(lat);
17 |
18 | p.addRequired('lat',@(a)isnumeric(a) && isvector(a) &&~isempty(a));
19 | p.addRequired('long',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
20 | p.addRequired('alt',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
21 | p.addRequired('heading',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
22 | p.addRequired('tilt',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
23 | p.addRequired('roll',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
24 |
25 | p.addParamValue('id',kml.getTempID('kml_camera'),@ischar);
26 | p.addParamValue('name','kml_camera',@ischar);
27 | p.addParamValue('altitudeMode','absolute',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
28 |
29 | p.addParamValue('timeStamp','',@ischar);
30 | p.addParamValue('timeSpanBegin','',@ischar);
31 | p.addParamValue('timeSpanEnd','',@ischar);
32 |
33 | p.parse(lat,long,alt,heading,tilt,roll,varargin{:});
34 |
35 | arg = p.Results;
36 |
37 |
38 | placemark = this.xml.createElement('Placemark');
39 | camera = this.xml.createElement('Camera');
40 |
41 | placemark.setAttribute('id',arg.id);
42 | placemark.appendChild(this.textNode('name',arg.name));
43 |
44 | if ~isempty(arg.timeStamp)
45 | timeStamp = this.xml.createElement('TimeStamp');
46 | timeStamp.appendChild(this.textNode('when',arg.timeStamp));
47 | placemark.appendChild(timeStamp);
48 | elseif ~isempty(arg.timeSpanBegin) || ~isempty(arg.timeSpanEnd)
49 | timeSpan = this.xml.createElement('TimeSpan');
50 | if ~isempty(arg.timeSpanBegin)
51 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin));
52 | end
53 |
54 | if ~isempty(arg.timeSpanEnd)
55 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd));
56 | end
57 | placemark.appendChild(timeSpan);
58 | end
59 |
60 | camera.appendChild(this.textNode('latitude',num2str(arg.lat)));
61 | camera.appendChild(this.textNode('longitude',num2str(arg.long)));
62 | camera.appendChild(this.textNode('altitude',num2str(arg.alt)));
63 | camera.appendChild(this.textNode('heading',num2str(arg.heading)));
64 | camera.appendChild(this.textNode('tilt',num2str(arg.tilt)));
65 | camera.appendChild(this.textNode('roll',num2str(arg.roll)));
66 | camera.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
67 |
68 | placemark.appendChild(camera);
69 | this.doc.appendChild(placemark);
70 |
71 | target.type = 'Placemark';
72 | target.id = arg.id;
73 | end
--------------------------------------------------------------------------------
/@kml/captureScreen.m:
--------------------------------------------------------------------------------
1 | function IM = captureScreen (view)
2 | %KML.CAPTURESCREEN(view) Capture a screenshot, and return an cell with the image of each monitor.
3 | %
4 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
5 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
6 |
7 | if nargin ==0
8 | view = false;
9 | end
10 | ge = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
11 | gd = ge.getScreenDevices;
12 |
13 | robot = java.awt.Robot;
14 |
15 | for i = 1:numel(gd)
16 | bounds = gd(i).getDefaultConfiguration.getBounds;
17 |
18 | width = bounds.getWidth();
19 | height = bounds.getHeight();
20 | left = bounds.getX;
21 | top = bounds.getY;
22 |
23 | im = zeros(height,width,3,'uint8');
24 | bimg = robot.createScreenCapture(java.awt.Rectangle(left, top, width, height));
25 | RGBA = bimg.getRGB(0,0,width,height,[],0,width);
26 | RGBA = typecast(RGBA, 'uint8');
27 |
28 | im(:,:,1) = reshape(RGBA(3:4:end),width,height).';
29 | im(:,:,2) = reshape(RGBA(2:4:end),width,height).';
30 | im(:,:,3) = reshape(RGBA(1:4:end),width,height).';
31 |
32 | IM{i} = im;
33 | end
34 |
35 | if view
36 | figure;
37 | N = numel(IM);
38 | for i = 1:N
39 | subplot(N,1,i);
40 | image(IM{i});
41 | axis equal tight
42 | end
43 | end
44 | end
--------------------------------------------------------------------------------
/@kml/colorbar.m:
--------------------------------------------------------------------------------
1 | function target = colorbar(this,cAxis,colorMap,varargin)
2 | ss = get(0,'ScreenSize')*.8;
3 |
4 | p = inputParser;
5 |
6 | p.addRequired('cAxis', @isnumeric);
7 | p.addRequired('colorMap', @isnumeric);
8 |
9 | p.addParamValue('type','vertical',@(a)ismember(lower(a),{'vertical','horizontal'}));
10 | p.addParamValue('tick',[],@isnumeric);
11 | p.addParamValue('tickLabel',{},@iscell);
12 |
13 |
14 |
15 | p.addParamValue('id','kml_colorbar',@ischar);
16 | p.addParamValue('name','kml_colorbar',@ischar);
17 | p.addParamValue('description','',@ischar);
18 | p.addParamValue('visibility',true,@islogical);
19 | p.addParamValue('rotation',0,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
20 | p.addParamValue('drawOrder',0,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
21 |
22 | p.addParamValue('timeStamp','',@ischar);
23 | p.addParamValue('timeSpanBegin','',@ischar);
24 | p.addParamValue('timeSpanEnd','',@ischar);
25 |
26 |
27 | p.parse(cAxis,colorMap,varargin{:});
28 |
29 | arg = p.Results;
30 |
31 | if numel(cAxis) > 2
32 | cAxis = [min(cAxis) max(cAxis)];
33 | end
34 |
35 | l = linspace(cAxis(1),cAxis(2),1000);
36 | fh = figure;
37 |
38 |
39 | if strcmpi(arg.type,'vertical')
40 | ratio = 40;
41 |
42 | pcolor([0*l.' 1+0*l.'],[l.' l.'],[l.' l.'])
43 |
44 | set(gcf,'Position',[0 0 ss(4)./ratio ss(4)]);%[ss(1)+ss(4)./ratio ss(2) ss(4)./ratio ss(4)]);
45 | set(gca,'XTick',[]);
46 | if ~isempty(arg.tick)
47 | set(gca,'YTick',arg.tick);
48 | end
49 | if ~isempty(arg.tickLabel)
50 | set(gca,'YTickLabel',arg.tickLabel);
51 | end
52 | sz = [2/ratio 1];
53 | overlayPos = [2 1];
54 | screenPos = [1 1];
55 | else
56 | ratio = 40;
57 | pcolor([l.' l.'],[0*l.' 1+0*l.'],[l.' l.'])
58 | set(gcf,'Position',[0 0 ss(3) ss(3)./ratio ]);%[ss(1) ss(2)+ss(3)./ratio ss(3) ss(3)./ratio ]);
59 | set(gca,'YTick',[]);
60 | if ~isempty(arg.tick)
61 | set(gca,'XTick',arg.tick);
62 | end
63 | if ~isempty(arg.tickLabel)
64 | set(gca,'XTickLabel',arg.tickLabel);
65 | end
66 | sz = [1 2/ratio];
67 | overlayPos = [1 (ratio-4)/2];
68 | screenPos = [1 1];
69 | end
70 |
71 | movegui(fh,'north');
72 |
73 | shading flat;
74 | caxis(cAxis);
75 | colormap(colorMap);
76 |
77 |
78 |
79 | name = 'Colorbar';
80 | basename = 'Colorbar';
81 |
82 | name = [name '.png'];
83 | k = 1;
84 | while ~isempty(dir(name))
85 | name = sprintf('%s (%i)%s',basename,k,'.png');
86 | k = k+1;
87 | end
88 |
89 | bgColor = [0 0 0];
90 | fgColor = [1 1 1];
91 |
92 | set(gca,'Color',bgColor,'XColor',fgColor,'YColor',fgColor);
93 | set(fh,'Color',bgColor);
94 | set(gca,'FontWeight','bold','FontSize',15)
95 | % grid on
96 | % set(gca,'GridLineStyle','-')
97 |
98 | % figure(fh)
99 | % drawnow
100 | % pause(1) %drawing on windows starts with a transparent window, better give some time for it to show, so we don't capture the background
101 | % drawnow
102 | % drawnow('expose');
103 | % im = getframe(fh);
104 | % drawnow('expose');
105 | % im = im.cdata;
106 |
107 | set(fh,'PaperPositionMode','auto','InvertHardcopy','off')
108 | print('-dpng','-r0',name,fh)
109 | im = imread(name);
110 |
111 | axc = ceil(bgColor*255);
112 | alphaMap = uint8(~(im(:,:,1)==axc(1) & im(:,:,2)==axc(2) & im(:,:,3)==axc(3))*255);
113 |
114 | imwrite(im,name,'Alpha',alphaMap);
115 | close(fh);
116 | drawnow
117 |
118 |
119 | %
120 | % Simple crosshairs
121 | % This screen overlay uses fractional positioning
122 | % to put the image in the exact center of the screen
123 | %
124 | % http://myserver/myimage.jpg
125 | %
126 | %
127 | %
128 | % 39.37878630116985
129 | %
130 | %
131 |
132 |
133 | overlay = this.xml.createElement('ScreenOverlay');
134 | overlayXY = this.xml.createElement('overlayXY');
135 | screenXY = this.xml.createElement('screenXY');
136 | size = this.xml.createElement('size');
137 | icon = this.xml.createElement('Icon');
138 |
139 | overlay.setAttribute('id',arg.id);
140 | overlay.appendChild(this.textNode('name',arg.name));
141 | overlay.appendChild(this.textNode('open','1'));
142 | overlay.appendChild(this.textNode('visibility',num2str(arg.visibility)));
143 | overlay.appendChild(this.textNode('description',arg.description));
144 | overlay.appendChild(this.textNode('drawOrder',num2str(arg.drawOrder)));
145 |
146 | if ~isempty(arg.timeStamp)
147 | timeStamp = this.xml.createElement('TimeStamp');
148 | timeStamp.appendChild(this.textNode('when',arg.timeStamp));
149 | overlay.appendChild(timeStamp);
150 | elseif ~isempty(arg.timeSpanBegin) || ~isempty(arg.timeSpanEnd)
151 | timeSpan = this.xml.createElement('TimeSpan');
152 | if ~isempty(arg.timeSpanBegin)
153 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin));
154 | end
155 |
156 | if ~isempty(arg.timeSpanEnd)
157 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd));
158 | end
159 | overlay.appendChild(timeSpan);
160 | end
161 |
162 | overlayXY.setAttribute('x',num2str(overlayPos(1),16))
163 | overlayXY.setAttribute('y',num2str(overlayPos(2),16))
164 | overlayXY.setAttribute('xunits','fraction')
165 | overlayXY.setAttribute('yunits','fraction')
166 |
167 | screenXY.setAttribute('x',num2str(screenPos(1),16))
168 | screenXY.setAttribute('y',num2str(screenPos(2),16))
169 | screenXY.setAttribute('xunits','fraction')
170 | screenXY.setAttribute('yunits','fraction')
171 |
172 | size.setAttribute('x',num2str(sz(1),16))
173 | size.setAttribute('y',num2str(sz(2),16))
174 | size.setAttribute('xunits','fraction')
175 | size.setAttribute('yunits','fraction')
176 | overlay.appendChild(this.textNode('rotation', num2str(arg.rotation)));
177 |
178 | icon.appendChild(this.textNode('href',name));
179 |
180 | overlay.appendChild(overlayXY);
181 | overlay.appendChild(screenXY);
182 | overlay.appendChild(size);
183 | overlay.appendChild(icon);
184 |
185 | this.doc.appendChild(overlay);
186 |
187 | target.id = arg.id;
188 | target.type = 'ScreenOverlay';
189 |
190 | this.addIncludeFile(name);
191 | end
--------------------------------------------------------------------------------
/@kml/contour.m:
--------------------------------------------------------------------------------
1 | function target = contour(this,long,lat,alt,varargin)
2 | %KML.CONTOUR(long,lat,alt) Create a contour of alt in a grid defined by long and lat.
3 | % Similar to built-in contour function
4 | %
5 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
6 | % $Revision: 1.4 $ $Date: 2012/02/08 16:00:00 $
7 |
8 | target = struct('type','','id','','coordinates_type','','coordinates_id','');
9 |
10 | p = inputParser;
11 |
12 | nlat = numel(lat);
13 |
14 | p.addRequired('lat', @(a)isnumeric(a) && ~isempty(a));
15 | p.addRequired('long', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
16 | p.addRequired('alt', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
17 |
18 | p.addParamValue('name','kml_contour',@ischar);
19 | p.addParamValue('id',kml.getTempID('kml_contour'),@ischar);
20 | p.addParamValue('description','',@ischar);
21 | p.addParamValue('visibility',true,@islogical);
22 | p.addParamValue('colorMap','jet',@ischar);
23 | p.addParamValue('numberOfLevels','auto',@(a)(ischar(a) && strcmpi(a,'auto')) ||(isnumeric(a)));
24 | p.addParamValue('altitude',1,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
25 | p.addParamValue('altitudeMode','clampToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
26 | p.addParamValue('showText',false,@islogical)
27 |
28 | p.addParamValue('noFolder',false,@islogical)
29 |
30 | p.addParamValue('levelStep',1,@isnumeric)
31 | p.addParamValue('labelSpacing',inf,@isnumeric)
32 | p.addParamValue('timeStamp','',@ischar);
33 | p.addParamValue('timeSpanBegin','',@ischar);
34 | p.addParamValue('timeSpanEnd','',@ischar);
35 | p.addParamValue('lineWidth',1,@isnumeric);
36 |
37 | p.parse(lat,long,alt,varargin{:});
38 |
39 | arg = p.Results;
40 |
41 | if arg.noFolder
42 | f = this;
43 | else
44 | f = this.createFolder(arg.name);
45 | end
46 |
47 | if isnumeric(arg.numberOfLevels)
48 | c = contours(lat,long,alt,arg.numberOfLevels);
49 | else
50 | c = contours(lat,long,alt);
51 | end
52 |
53 | minAlt = min(min(alt));
54 | maxalt = max(max(alt));
55 |
56 |
57 | i = 1; k=1;
58 | while true
59 | l = c(1,i);
60 | n = c(2,i);
61 | C(k).lat = c(1,(i+1):(i+n));
62 | C(k).long = c(2,(i+1):(i+n));
63 | C(k).l = l;
64 | i = i + n + 1;
65 | k = k + 1;
66 | if i > size(c,2)
67 | break;
68 | end
69 | end
70 |
71 | levels = unique([C(:).l]);
72 | shownLevels = levels(1:arg.levelStep:numel(levels));
73 |
74 | ncolors = 100;
75 | cmap = feval(arg.colorMap,ncolors);
76 | levelsCMAP = linspace(min(levels),max(levels),ncolors);
77 | middleLevel = levels(ceil(numel(levels)/2));
78 |
79 | for i = 1:numel(C)
80 | clev = C(i).l;
81 | iC = find(levels==clev);
82 | if clev <= middleLevel
83 | clev = clev - 1;
84 | end
85 | if numel(levels) > 1
86 | iC = round(interp1(levelsCMAP,linspace(0,ncolors-1,numel(levelsCMAP)),clev,'linear',0));
87 | else
88 | iC = 1;
89 | end
90 | color = cmap(iC+1 ,:);
91 |
92 | colorHex = kml.color2kmlHex(color);
93 |
94 |
95 | target(i) = f.plot(C(i).long,C(i).lat, 'lineColor', colorHex, ...
96 | 'lineWidth',arg.lineWidth,...
97 | 'altitudeMode',arg.altitudeMode, ...
98 | 'altitude',arg.altitude,...
99 | 'visibility',arg.visibility, ...
100 | 'name',sprintf('Level %g',C(i).l), ...
101 | 'timeStamp', arg.timeStamp , ...
102 | 'timeSpanBegin', arg.timeSpanBegin , ...
103 | 'timeSpanEnd', arg.timeSpanEnd, ...
104 | 'id',[arg.id '_' num2str(i)] ...
105 | );
106 |
107 | if arg.showText && ismember(C(i).l,shownLevels)
108 | N = numel(C(i).lat);
109 | if ~isfinite(arg.labelSpacing)
110 | R = randi(N,1);
111 | latTxt = interp1(1:N,C(i).lat,R);
112 | longTxt = interp1(1:N,C(i).long,R);
113 | f.text(longTxt,latTxt,0,sprintf('%g',C(i).l));
114 | else
115 | dist = kml.ll2dist(C(i).long(1:end-1),C(i).lat(1:end-1), ...
116 | C(i).long(2:end),C(i).lat(2:end));
117 | dist = [0 cumsum(dist)];
118 | for d = 1:arg.labelSpacing:dist(end);
119 | latTxt = interp1(dist,C(i).lat,d);
120 | longTxt = interp1(dist,C(i).long,d);
121 | f.text(longTxt,latTxt,0,sprintf('%g',C(i).l));
122 | end
123 | end
124 | end
125 | end
126 | end
--------------------------------------------------------------------------------
/@kml/contour3.m:
--------------------------------------------------------------------------------
1 | function target = contour3(this,long,lat,alt,varargin)
2 | %KML.CONTOUR(long,lat,alt) Create a 3D contour of alt in a grid defined by long and lat.
3 | % The altitude of each line is given by its associated contour level
4 | % Similar to built-in contour3 function
5 | %
6 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
7 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
8 |
9 | target = struct('type','','id','','coordinates_type','','coordinates_id','');
10 |
11 | p = inputParser;
12 |
13 | nlat = numel(lat);
14 |
15 | p.addRequired('lat', @(a)isnumeric(a) && ~isempty(a));
16 | p.addRequired('long', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
17 | p.addRequired('alt', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
18 |
19 | p.addParamValue('name','kml_contour3',@ischar);
20 | p.addParamValue('id',kml.getTempID('kml_contour3'),@ischar);
21 | p.addParamValue('description','',@ischar);
22 | p.addParamValue('visibility',true,@islogical);
23 | p.addParamValue('extrude',false,@islogical);
24 | p.addParamValue('colorMap','jet',@ischar);
25 | p.addParamValue('numberOfLevels','auto',@(a)(ischar(a) && strcmpi(a,'auto')) ||(isnumeric(a)));
26 | p.addParamValue('altitudeMode','relativeToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
27 |
28 | p.addParamValue('noFolder',false,@islogical)
29 |
30 | p.addParamValue('showText',false,@islogical)
31 | p.addParamValue('levelStep',1,@isnumeric)
32 | p.addParamValue('labelSpacing',inf,@isnumeric)
33 |
34 | p.addParamValue('timeStamp','',@ischar);
35 | p.addParamValue('timeSpanBegin','',@ischar);
36 | p.addParamValue('timeSpanEnd','',@ischar);
37 |
38 | p.addParamValue('lineWidth',1,@isnumeric);
39 |
40 | p.parse(lat,long,alt,varargin{:});
41 |
42 | arg = p.Results;
43 |
44 | if arg.noFolder
45 | f = this;
46 | else
47 | f = this.createFolder(arg.name);
48 | end
49 |
50 | if isnumeric(arg.numberOfLevels)
51 | c = contours(lat,long,alt,arg.numberOfLevels);
52 | else
53 | c = contours(lat,long,alt);
54 | end
55 |
56 | minAlt = min(min(alt));
57 | maxAlt = max(max(alt));
58 |
59 | i = 1; k=1;
60 | while true
61 | l = c(1,i);
62 | n = c(2,i);
63 | C(k).lat = c(1,(i+1):(i+n));
64 | C(k).long = c(2,(i+1):(i+n));
65 | C(k).l = l;
66 | i = i + n + 1;
67 | k = k + 1;
68 | if i > size(c,2)
69 | break;
70 | end
71 | end
72 |
73 | levels = unique([C(:).l]);
74 | shownLevels = levels(1:arg.levelStep:numel(levels));
75 |
76 | ncolors = 100;
77 | cmap = feval(arg.colorMap,ncolors);
78 | levelsCMAP = linspace(min(levels),max(levels),ncolors);
79 | middleLevel = levels(ceil(numel(levels)/2));
80 |
81 | for i = 1:numel(C)
82 |
83 | clev = C(i).l;
84 | iC = find(levels==clev);
85 | if clev <= middleLevel
86 | clev = clev - 1;
87 | end
88 |
89 | if numel(levels) > 1
90 | iC = round(interp1(levelsCMAP,linspace(0,ncolors-1,numel(levelsCMAP)),clev,'linear',0));
91 | else
92 | iC = 1;
93 | end
94 |
95 | color = cmap(iC+1 ,:);
96 |
97 | colorHex = kml.color2kmlHex(color);
98 |
99 | polyColor = colorHex;
100 |
101 | if arg.extrude
102 | polyColor(1:2) = 'FF';
103 | colorHex(1:2) = '00';
104 | target(end+1) = f.poly(C(i).long,C(i).lat, 'lineColor', colorHex, ...
105 | 'altitudeMode',arg.altitudeMode, ...
106 | 'altitude',C(i).l,...
107 | 'visibility',arg.visibility, ...
108 | 'name',sprintf('Level %g',C(i).l), ...
109 | 'timeStamp', arg.timeStamp , ...
110 | 'timeSpanBegin', arg.timeSpanBegin , ...
111 | 'timeSpanEnd', arg.timeSpanEnd, ...
112 | 'extrude',arg.extrude, ...
113 | 'polyColor',polyColor, ...
114 | 'id',[arg.id '_poly_' num2str(i)] ...
115 | );
116 | else
117 | polyColor(1:2) = '00';
118 |
119 | target(end+1) = f.plot(C(i).long,C(i).lat, 'lineColor', colorHex, ...
120 | 'lineWidth',arg.lineWidth,...
121 | 'altitudeMode',arg.altitudeMode, ...
122 | 'altitude',C(i).l,...
123 | 'visibility',arg.visibility, ...
124 | 'name',sprintf('Level %g',C(i).l), ...
125 | 'timeStamp', arg.timeStamp , ...
126 | 'timeSpanBegin', arg.timeSpanBegin , ...
127 | 'timeSpanEnd', arg.timeSpanEnd, ...
128 | 'extrude',arg.extrude, ...
129 | 'polyColor',polyColor, ...
130 | 'id',[arg.id '_plot_' num2str(i)] ...
131 | );
132 | end
133 |
134 | if arg.showText && ismember(C(i).l,shownLevels)
135 | N = numel(C(i).lat);
136 | altTxt = C(i).l;
137 | if ~isfinite(arg.labelSpacing)
138 | R = randi(N,1);
139 | latTxt = interp1(1:N,C(i).lat,R);
140 | longTxt = interp1(1:N,C(i).long,R);
141 |
142 | target(end+1) = f.text(longTxt,latTxt,altTxt,sprintf('%g',C(i).l), 'id',[arg.id '_text_' num2str(i)]);
143 | else
144 | dist = kml.ll2dist(C(i).long(1:end-1),C(i).lat(1:end-1), ...
145 | C(i).long(2:end),C(i).lat(2:end));
146 | dist = [0 cumsum(dist)];
147 | for d = 1:arg.labelSpacing:dist(end);
148 | latTxt = interp1(dist,C(i).lat,d);
149 | longTxt = interp1(dist,C(i).long,d);
150 | target(end+1) = f.text(longTxt,latTxt,altTxt,sprintf('%g',C(i).l), 'id',[arg.id '_text_' num2str(i) '_' num2str(d)]);
151 | end
152 | end
153 | end
154 |
155 | end
156 | target(1) = []; %remove the empty initial field
157 | end
--------------------------------------------------------------------------------
/@kml/contourf.m:
--------------------------------------------------------------------------------
1 | function target = contourf(this,long,lat,alt,varargin)
2 | %KML.CONTOURF(long,lat,alt) Create a filled contour of alt in a grid defined by long and lat.
3 | % Similar to built-in contour function
4 | %
5 | % 17.05.2013 - Added suggestion by Keith Epstein to allow changing line width and color
6 | %
7 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
8 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
9 |
10 |
11 | target = struct('type','','id','');
12 |
13 | p = inputParser;
14 |
15 | nlat = numel(lat);
16 |
17 | p.addRequired('lat', @(a)isnumeric(a) && ~isempty(a));
18 | p.addRequired('long', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
19 | p.addRequired('alt', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
20 |
21 | p.addParamValue('name','kml_contourf',@ischar);
22 | p.addParamValue('id',kml.getTempID('kml_contourf'),@ischar);
23 | p.addParamValue('description','',@ischar);
24 | p.addParamValue('visibility',true,@islogical);
25 | p.addParamValue('transparency',1,@isnumeric);
26 | p.addParamValue('lineWidth',1,@isnumeric);
27 | p.addParamValue('lineColor','',@(x)ischar(x)||isempty(x));
28 |
29 | p.addParamValue('colorMap','jet',@ischar);
30 | p.addParamValue('numberOfLevels','auto',@(a)(ischar(a) && strcmpi(a,'auto')) ||(isnumeric(a)));
31 |
32 | p.addParamValue('noFolder',false,@islogical)
33 |
34 | p.addParamValue('showText',false,@islogical)
35 | p.addParamValue('levelStep',1,@isnumeric)
36 | p.addParamValue('labelSpacing',inf,@isnumeric)
37 |
38 | p.addParamValue('timeStamp','',@ischar);
39 | p.addParamValue('timeSpanBegin','',@ischar);
40 | p.addParamValue('timeSpanEnd','',@ischar);
41 |
42 | p.parse(lat,long,alt,varargin{:});
43 |
44 | arg = p.Results;
45 |
46 | if arg.noFolder
47 | f = this;
48 | else
49 | f = this.createFolder(arg.name);
50 | end
51 |
52 | minAlt = min(alt(:));
53 | maxAlt = max(alt(:));
54 |
55 | if isnumeric(arg.numberOfLevels)
56 | c = contours(long,lat,alt,arg.numberOfLevels);
57 | else
58 | dAlt = maxAlt-minAlt;
59 | dAlt10 = 10^(floor(log10(dAlt)));
60 | nsteps = dAlt/dAlt10;
61 | if nsteps < 1.2
62 | dAlt10 = dAlt10/10;
63 | elseif nsteps < 2.4
64 | dAlt10 = dAlt10/5;
65 | elseif nsteps < 6
66 | dAlt10 = dAlt10/2;
67 | end
68 |
69 | if minAlt < 0 && maxAlt > 0
70 | neg = -dAlt10:-dAlt10:minAlt;
71 | pos = 0:dAlt10:maxAlt;
72 | levels = [fliplr(neg) pos];
73 | elseif minAlt < 0
74 | minLevel = minAlt - (dAlt10 - mod(-minAlt,dAlt10));
75 | levels = minLevel+dAlt10:dAlt10:maxAlt;
76 | else
77 | minLevel = minAlt + (dAlt10 - mod(minAlt,dAlt10));
78 | levels = minLevel:dAlt10:maxAlt;
79 | end
80 | levels = [minAlt levels];
81 | c = contours(long,lat,alt,levels);
82 | end
83 |
84 |
85 |
86 | % To avoid contours with open end, it is necessary to redo the contour
87 | % calculation using an extended matrix, with very low borders.
88 |
89 | levels = [];
90 | i = 1; k=1;
91 | while true
92 | l = c(1,i);
93 | n = c(2,i);
94 | levels = [levels; l];
95 | i = i + n + 1;
96 | k = k + 1;
97 | if i > size(c,2)
98 | break;
99 | end
100 | end
101 |
102 | levels = unique(levels);
103 |
104 | [m,n] = size(alt);
105 |
106 | alt = [NaN(1, n+2); NaN(m,1) alt NaN(m,1); NaN(1, n+2)];
107 | lat = [2.*lat(1,[1 1:end end]) - lat(2,[1 1:end end]); ...
108 | (2.*lat(:,1)-lat(:,2)), lat, (2.*lat(:,end)-lat(:,end-1)); ...
109 | 2.*lat(end,[1 1:end end]) - lat(end-1,[1 1:end end])];
110 |
111 | long = long.';
112 | long = [2.*long(1,[1 1:end end]) - long(2,[1 1:end end]); ...
113 | (2.*long(:,1)-long(:,2)), long, (2.*long(:,end)-long(:,end-1)); ...
114 | 2.*long(end,[1 1:end end]) - long(end-1,[1 1:end end])];
115 |
116 | long = long.';
117 |
118 |
119 |
120 | alt(isnan(alt)) = minAlt - 1e4.*(maxAlt - minAlt);
121 |
122 | c = contours(long,lat,alt,levels);
123 |
124 | i = 1; k=1;
125 | while true
126 | l = c(1,i);
127 | n = c(2,i);
128 | C(k).long = c(1,(i+1):(i+n));
129 | C(k).lat = c(2,(i+1):(i+n));
130 | C(k).l = l;
131 | if n<2
132 | C(k).area = 0;
133 | else
134 | C(k).area = sum(diff(C(k).lat) .* (C(k).long(1 : n - 1) + C(k).long(2 : n)) / 2);
135 | end
136 |
137 |
138 | i = i + n + 1;
139 | k = k + 1;
140 | if i > size(c,2)
141 | break;
142 | end
143 | end
144 |
145 |
146 | levels = unique([C(:).l]);
147 | minLevel = min(levels);
148 | shownLevels = levels(1:arg.levelStep:numel(levels));
149 | areas = -unique(-abs([C(:).area]));
150 | [~,ixMA] = max(abs([C(:).area]));
151 | maxArea = C(ixMA).area;
152 |
153 | ncolors = 100;
154 | cmap = feval(arg.colorMap,ncolors);
155 | levelsCMAP = linspace(min(levels),max(levels),ncolors);
156 | middleLevel = levels(ceil(numel(levels)/2));
157 |
158 |
159 | % Don't fill contours below the minimum level
160 | showMinLevel=any(levels <= minAlt);
161 |
162 | for a = areas;
163 | for i = 1:numel(C)
164 | if abs(C(i).area) == a
165 | clev = C(i).l;
166 | %iC = find(levels==clev);
167 | % if clev <= middleLevel
168 | % clev = clev - 1;
169 | % end
170 |
171 | if (sign(C(i).area) ~=sign(maxArea)),
172 | kk=find(levels==clev);
173 | kk0 = 1 + sum(levels<=minAlt) * (~showMinLevel);
174 | if (kk > kk0)
175 | clev=levels(kk-1); % in valley, use color for lower level
176 | elseif (kk == kk0)
177 | break;
178 | else
179 | break;
180 | end
181 | end
182 |
183 | if numel(levels) > 1
184 | iC = floor(interp1(levelsCMAP,linspace(0,ncolors-1,numel(levelsCMAP)),clev,'linear',0));
185 | else
186 | iC = 1;
187 | end
188 |
189 | color = cmap(iC+1 ,:);
190 |
191 | colorHex = kml.color2kmlHex([color arg.transparency]);
192 |
193 | % debug: to view while plotting
194 | % fig(12345)
195 | % hold on
196 | % patch(C(i).long,C(i).lat,color)
197 |
198 |
199 | if arg.lineWidth > 0
200 | lineColor = '00000000';
201 | else
202 | if isempty(arg.lineColor)
203 | lineColor = ['FF' colorHex(3:end)];
204 | else
205 | lineColor = 'FF000000';
206 | end
207 | end
208 |
209 | target(end+1) = f.poly3(C(i).long,C(i).lat,zeros(size(C(i).lat)), 'polyColor', colorHex, ...
210 | 'lineColor',lineColor,...
211 | 'lineWidth',arg.lineWidth, ...
212 | 'altitudeMode','clampToGround', ...
213 | 'visibility',arg.visibility, ...
214 | 'name',sprintf('Level %g',C(i).l), ...
215 | 'timeStamp', arg.timeStamp , ...
216 | 'timeSpanBegin', arg.timeSpanBegin , ...
217 | 'timeSpanEnd', arg.timeSpanEnd, ...
218 | 'id',[arg.id '_poly_' num2str(i)] ...
219 | );
220 | if arg.showText && ismember(C(i).l,shownLevels)
221 | N = numel(C(i).lat);
222 | if ~isfinite(arg.labelSpacing)
223 | R = randi(N,1);
224 | latTxt = interp1(1:N,C(i).lat,R);
225 | longTxt = interp1(1:N,C(i).long,R);
226 | target(end+1) = f.text(longTxt,latTxt,0,sprintf('%g',C(i).l), 'id',[arg.id '_text_' num2str(i)]);
227 | else
228 | dist = kml.ll2dist(C(i).long(1:end-1),C(i).lat(1:end-1), ...
229 | C(i).long(2:end),C(i).lat(2:end));
230 | dist = [0 cumsum(dist)];
231 | for d = 1:arg.labelSpacing:dist(end);
232 | latTxt = interp1(dist,C(i).lat,d);
233 | longTxt = interp1(dist,C(i).long,d);
234 | target(end+1) = f.text(longTxt,latTxt,0,sprintf('%g',C(i).l), 'id',[arg.id '_text_' num2str(i) '_' num2str(d)]);
235 | end
236 | end
237 | end
238 | end
239 | end
240 | end
241 | target(1) = []; %remove the empty initial field
242 | end
--------------------------------------------------------------------------------
/@kml/createFolder.m:
--------------------------------------------------------------------------------
1 | function f = createFolder(this,foldername)
2 | % DEPRECATED, renamed as newFolder
3 | f = this.newFolder(foldername);
4 | end
--------------------------------------------------------------------------------
/@kml/model.m:
--------------------------------------------------------------------------------
1 | function target = model(this,long,lat,alt,heading,tilt,roll,varargin)
2 | %KML.MODEL(long,lat,alt,heading,tilt,roll) Places the 3D model (specified by the pair
3 | % attribute 'model','modelfile.dae') in the position and orientation given by long,
4 | % lat, alt, heading, tilt and roll. If the inputs represent a vector of points, the
5 | % model is repeated in each of them.
6 | %
7 | % Many model files can be found in the Google 3D Warehouse website.
8 | %
9 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
10 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
11 |
12 | target = struct('type','','id','');
13 |
14 | [long,lat,heading,tilt,roll] = this.checkUnit(long,lat,heading,tilt,roll);
15 |
16 | p = inputParser;
17 |
18 | nlat = numel(lat);
19 |
20 | p.addRequired('lat',@(a)isnumeric(a) && isvector(a) &&~isempty(a));
21 | p.addRequired('long',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
22 | p.addRequired('alt',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
23 | p.addRequired('heading',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
24 | p.addRequired('tilt',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
25 | p.addRequired('roll',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
26 |
27 | p.addParamValue('id',kml.getTempID('kml_model'),@ischar);
28 | p.addParamValue('name','kml_model',@ischar);
29 | p.addParamValue('description','',@ischar);
30 | p.addParamValue('visibility',true,@islogical);
31 | p.addParamValue('model','',@ischar);
32 | p.addParamValue('scaleX',1,@(a)isnumeric(a) && (numel(a)==nlat || numel(a)==1));
33 | p.addParamValue('scaleY',1,@(a)isnumeric(a) && (numel(a)==nlat || numel(a)==1));
34 | p.addParamValue('scaleZ',1,@(a)isnumeric(a) && (numel(a)==nlat || numel(a)==1));
35 | p.addParamValue('scale',1, @(a)isnumeric(a) && (numel(a)==nlat || numel(a)==1));
36 | p.addParamValue('altitudeMode','relativeToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
37 |
38 | p.addParamValue('timeStamp','',@ischar);
39 | p.addParamValue('timeSpanBegin','',@ischar);
40 | p.addParamValue('timeSpanEnd','',@ischar);
41 |
42 | p.parse(lat,long,alt,heading,tilt,roll,varargin{:});
43 |
44 | arg = p.Results;
45 |
46 |
47 | if isempty(arg.model)
48 | error('Missing model parameter')
49 | end
50 |
51 | arg.scaleX = arg.scaleX .*arg.scale;
52 | arg.scaleY = arg.scaleY .*arg.scale;
53 | arg.scaleZ = arg.scaleZ .*arg.scale;
54 |
55 | if numel(arg.scaleX)==1 && nlat>1
56 | arg.scaleX = repmat(arg.scaleX,size(lat));
57 | end
58 |
59 | if numel(arg.scaleY)==1 && nlat>1
60 | arg.scaleY = repmat(arg.scaleY,size(lat));
61 | end
62 |
63 | if numel(arg.scaleZ)==1 && nlat>1
64 | arg.scaleZ = repmat(arg.scaleZ,size(lat));
65 | end
66 |
67 |
68 | for i = 1:nlat
69 | target(i).type = 'Placemark';
70 | target(i).id = [arg.id '_' num2str(i)];
71 | target(i).location_id = ['Location_' target(i).id ];
72 | target(i).orientation_id = ['Orientation_' target(i).id ];
73 | target(i).scale_id = ['Scale_' target(i).id ];
74 | target(i).model_id = ['Model_' target(i).id ];
75 |
76 | placemark = this.xml.createElement('Placemark');
77 | model = this.xml.createElement('Model');
78 | location = this.xml.createElement('Location');
79 | orientation = this.xml.createElement('Orientation');
80 | scale = this.xml.createElement('Scale');
81 | link = this.xml.createElement('Link');
82 |
83 | placemark.setAttribute('id',target(i).id);
84 | placemark.appendChild(this.textNode('name',arg.name));
85 | placemark.appendChild(this.textNode('visibility',num2str(arg.visibility)));
86 | placemark.appendChild(this.textNode('description',arg.description));
87 |
88 | if ~isempty(arg.timeStamp)
89 | timeStamp = this.xml.createElement('TimeStamp');
90 | timeStamp.appendChild(this.textNode('when',arg.timeStamp));
91 | placemark.appendChild(timeStamp);
92 | elseif ~isempty(arg.timeSpanBegin) || ~isempty(arg.timeSpanEnd)
93 | timeSpan = this.xml.createElement('TimeSpan');
94 | if ~isempty(arg.timeSpanBegin)
95 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin));
96 | end
97 |
98 | if ~isempty(arg.timeSpanEnd)
99 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd));
100 | end
101 | placemark.appendChild(timeSpan);
102 | end
103 |
104 | location.setAttribute('id',target(i).location_id);
105 | location.appendChild(this.textNode('latitude', num2str(lat(i),16)));
106 | location.appendChild(this.textNode('longitude', num2str(long(i),16)));
107 | location.appendChild(this.textNode('altitude', num2str(alt(i),16)));
108 |
109 | orientation.setAttribute('id',target(i).orientation_id);
110 | orientation.appendChild(this.textNode('heading', num2str(heading(i))));
111 | orientation.appendChild(this.textNode('tilt', num2str(tilt(i))));
112 | orientation.appendChild(this.textNode('roll', num2str(roll(i))));
113 |
114 | scale.setAttribute('id',target(i).scale_id);
115 | scale.appendChild(this.textNode('x', num2str(arg.scaleX(i))));
116 | scale.appendChild(this.textNode('y', num2str(arg.scaleY(i))));
117 | scale.appendChild(this.textNode('z', num2str(arg.scaleZ(i))));
118 |
119 | link.appendChild(this.textNode('href',arg.model));
120 |
121 | model.setAttribute('id',target(i).model_id);
122 | model.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
123 |
124 | model.appendChild(location);
125 | model.appendChild(orientation);
126 | model.appendChild(scale);
127 | model.appendChild(link);
128 |
129 | placemark.appendChild(model);
130 | this.doc.appendChild(placemark);
131 | end
132 | this.addIncludeFile(arg.model);
133 |
134 | end
--------------------------------------------------------------------------------
/@kml/modelTour.m:
--------------------------------------------------------------------------------
1 | function modelTour(this,time,long,lat,alt,heading,tilt,roll,varargin)
2 | %THIS FUNCTION IS DEPRECATED - USE KML.NEWANIATION INSTEAD
3 | %KML.MODELTOUR (long,lat,alt,heading,tilt,roll) Animates a 3D model (specified by the pair
4 | % attribute 'model','modelfile.dae') in the position and orientation given by long,
5 | % lat, alt, heading, tilt and roll. The time input controls how long the model takes
6 | % to fly from one coordinate to the next.
7 | %
8 | % Many model files can be found in the Google 3D Warehouse website.
9 | %
10 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
11 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
12 |
13 | [long,lat,heading,tilt,roll] = this.checkUnit(long,lat,heading,tilt,roll);
14 |
15 | p = inputParser;
16 |
17 | nlat = numel(lat);
18 |
19 | p.addRequired('time',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
20 | p.addRequired('lat',@(a)isnumeric(a) && isvector(a) &&~isempty(a));
21 | p.addRequired('long',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
22 | p.addRequired('alt',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
23 | p.addRequired('heading',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
24 | p.addRequired('tilt',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
25 | p.addRequired('roll',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
26 |
27 | p.addParamValue('id','kml_modelTour',@ischar);
28 | p.addParamValue('name','kml_modelTour',@ischar);
29 | p.addParamValue('description','',@ischar);
30 | p.addParamValue('visibility',true,@islogical);
31 | p.addParamValue('model','',@ischar);
32 | p.addParamValue('scaleX',1,@(a)isnumeric(a) && (numel(a)==nlat || numel(a)==1));
33 | p.addParamValue('scaleY',1,@(a)isnumeric(a) && (numel(a)==nlat || numel(a)==1));
34 | p.addParamValue('scaleZ',1,@(a)isnumeric(a) && (numel(a)==nlat || numel(a)==1));
35 | p.addParamValue('scale',1, @(a)isnumeric(a) && (numel(a)==nlat || numel(a)==1));
36 | p.addParamValue('altitudeMode','relativeToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
37 |
38 | p.addParamValue('tourName','Play Me!',@ischar);
39 | p.addParamValue('cameraMode','above',@(a)ismember(a,{'behind','above','fixed'}));
40 | p.addParamValue('cameraDistance',1e3,@isnumeric);
41 |
42 |
43 | p.parse(time,lat,long,alt,heading,tilt,roll,varargin{:});
44 |
45 | arg = p.Results;
46 |
47 |
48 | if isempty(arg.model)
49 | error('Missing model parameter')
50 | end
51 |
52 | arg.scaleX = arg.scaleX .*arg.scale;
53 | arg.scaleY = arg.scaleY .*arg.scale;
54 | arg.scaleZ = arg.scaleZ .*arg.scale;
55 |
56 | if numel(arg.scaleX)==1 && nlat>1
57 | arg.scaleX = repmat(arg.scaleX,size(lat));
58 | end
59 |
60 | if numel(arg.scaleY)==1 && nlat>1
61 | arg.scaleY = repmat(arg.scaleY,size(lat));
62 | end
63 |
64 | if numel(arg.scaleZ)==1 && nlat>1
65 | arg.scaleZ = repmat(arg.scaleZ,size(lat));
66 | end
67 |
68 |
69 | locationID = [arg.id '_location'];
70 | orientationID = [arg.id '_orientation'];
71 | scaleID = [arg.id '_scale'];
72 |
73 | placemark = this.xml.createElement('Placemark');
74 | model = this.xml.createElement('Model');
75 | location = this.xml.createElement('Location');
76 | orientation = this.xml.createElement('Orientation');
77 | scale = this.xml.createElement('Scale');
78 | link = this.xml.createElement('Link');
79 |
80 | placemark.setAttribute('id',arg.id);
81 | placemark.appendChild(this.textNode('name',arg.name));
82 | placemark.appendChild(this.textNode('visibility',num2str(arg.visibility)));
83 | placemark.appendChild(this.textNode('description',arg.description));
84 |
85 | location.setAttribute('id',locationID);
86 | location.appendChild(this.textNode('latitude', num2str(lat(1),16)));
87 | location.appendChild(this.textNode('longitude', num2str(long(1),16)));
88 | location.appendChild(this.textNode('altitude', num2str(alt(1),16)));
89 |
90 | orientation.setAttribute('id',orientationID);
91 | orientation.appendChild(this.textNode('heading', num2str(heading(1))));
92 | orientation.appendChild(this.textNode('tilt', num2str(tilt(1))));
93 | orientation.appendChild(this.textNode('roll', num2str(roll(1))));
94 |
95 | scale.setAttribute('id',scaleID);
96 | scale.appendChild(this.textNode('x', num2str(arg.scaleX(1))));
97 | scale.appendChild(this.textNode('y', num2str(arg.scaleY(1))));
98 | scale.appendChild(this.textNode('z', num2str(arg.scaleZ(1))));
99 |
100 | link.appendChild(this.textNode('href',arg.model));
101 |
102 | model.setAttribute('id',['Model_' arg.id]);
103 | model.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
104 |
105 | model.appendChild(location);
106 | model.appendChild(orientation);
107 | model.appendChild(scale);
108 | model.appendChild(link);
109 |
110 | placemark.appendChild(model);
111 | this.doc.appendChild(placemark);
112 |
113 | tour = this.xml.createElement('gx:Tour');
114 | playlist = this.xml.createElement('gx:Playlist');
115 | tour.appendChild(this.textNode('name',arg.tourName));
116 |
117 | for i = 2:nlat-1
118 |
119 | dT = time(i)-time(i-1);
120 |
121 | % Update object position
122 | animUpdate = this.xml.createElement('gx:AnimatedUpdate');
123 | update = this.xml.createElement('Update');
124 | change = this.xml.createElement('Change');
125 | location = this.xml.createElement('Location');
126 | orientation = this.xml.createElement('Orientation');
127 | scale = this.xml.createElement('Scale');
128 |
129 | animUpdate.appendChild(this.textNode('gx:duration',num2str(dT)));
130 |
131 | location.setAttribute('targetId',locationID);
132 | location.appendChild(this.textNode('latitude', num2str(lat(i),16)));
133 | location.appendChild(this.textNode('longitude', num2str(long(i),16)));
134 | location.appendChild(this.textNode('altitude', num2str(alt(i),16)));
135 |
136 | orientation.setAttribute('targetId',orientationID);
137 | orientation.appendChild(this.textNode('heading', num2str(heading(i))));
138 | orientation.appendChild(this.textNode('tilt', num2str(tilt(i))));
139 | orientation.appendChild(this.textNode('roll', num2str(roll(i))));
140 |
141 | scale.setAttribute('targetId',scaleID);
142 | scale.appendChild(this.textNode('x', num2str(arg.scaleX(i))));
143 | scale.appendChild(this.textNode('y', num2str(arg.scaleY(i))));
144 | scale.appendChild(this.textNode('z', num2str(arg.scaleZ(i))));
145 |
146 | change.appendChild(location);
147 | change.appendChild(orientation);
148 | change.appendChild(scale);
149 |
150 | update.appendChild(this.textNode('targetHref',''));
151 | update.appendChild(change);
152 | animUpdate.appendChild(update);
153 |
154 | playlist.appendChild(animUpdate);
155 |
156 | % Update camera position
157 | switch arg.cameraMode
158 | case 'fixed'
159 | wait = this.xml.createElement('gx:Wait');
160 | wait.appendChild(this.textNode('gx:duration',num2str(dT)));
161 | playlist.appendChild(wait);
162 | case 'behind'
163 | dS = [long(i+1) - long(i-1); lat(i+1) - lat(i-1);];
164 | dS = arg.cameraDistance * dS./sqrt(sum(dS.^2))/1e6;
165 |
166 | flyTo = this.xml.createElement('gx:FlyTo');
167 | flyTo.appendChild(this.textNode('gx:duration',num2str(dT)));
168 | flyTo.appendChild(this.textNode('gx:flyToMode','smooth'));
169 | camera = this.xml.createElement('Camera');
170 | camera.appendChild(this.textNode('longitude',num2str(long(i)-dS(1),16)));
171 | camera.appendChild(this.textNode('latitude',num2str(lat(i)-dS(2),16)));
172 | camera.appendChild(this.textNode('altitude',num2str(alt(i),16)));
173 | h = heading(i)-180;
174 |
175 | if h < -360
176 | h = 720+h;
177 | elseif h>360
178 | h = h-720;
179 | end
180 |
181 | camera.appendChild(this.textNode('heading',num2str(h)));
182 | camera.appendChild(this.textNode('tilt',num2str(90)));
183 | camera.appendChild(this.textNode('roll',num2str(0)));
184 | camera.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
185 |
186 | flyTo.appendChild(camera);
187 | playlist.appendChild(flyTo);
188 | case 'above'
189 |
190 | flyTo = this.xml.createElement('gx:FlyTo');
191 | flyTo.appendChild(this.textNode('gx:duration',num2str(dT)));
192 | flyTo.appendChild(this.textNode('gx:flyToMode','smooth'));
193 | lookAt = this.xml.createElement('LookAt');
194 | lookAt.appendChild(this.textNode('longitude',num2str(long(i),16)));
195 | lookAt.appendChild(this.textNode('latitude',num2str(lat(i),16)));
196 | lookAt.appendChild(this.textNode('altitude',num2str(alt(i) + arg.cameraDistance,16)));
197 | lookAt.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
198 |
199 | flyTo.appendChild(lookAt);
200 | playlist.appendChild(flyTo);
201 | end
202 | end
203 |
204 | tour.appendChild(playlist);
205 | this.doc.appendChild(tour);
206 |
207 | this.addIncludeFile(arg.model);
208 | end
--------------------------------------------------------------------------------
/@kml/newAnimation.m:
--------------------------------------------------------------------------------
1 | function f = newAnimation(this,animName)
2 | %KML.NEWANIMATION(folderName) Creates an animation storyboard inside an kml (or another folder).
3 | % Example of use:
4 | %
5 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
6 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
7 |
8 | if nargin < 2
9 | animName = 'Unnamed Animation';
10 | end
11 | f = kmlAnimation(this,animName);
12 | end
--------------------------------------------------------------------------------
/@kml/newFolder.m:
--------------------------------------------------------------------------------
1 | function f = newFolder(this,foldername)
2 | %KML.NEWFOLDER(folderName) Creates a folder inside an kml (or another folder).
3 | % The folder behaves exactly as a KML object.
4 | % Example of use:
5 | % k = kml;
6 | % f = kml.createFolder('My Folder');
7 | % t = linspace(0,2*pi,1000);
8 | % f.plot(t,sin(t));
9 | % k.run
10 | %
11 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
12 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
13 |
14 | if nargin < 2
15 | foldername = 'Unnamed Folder';
16 | end
17 | f = kml(foldername,this);
18 | end
--------------------------------------------------------------------------------
/@kml/overlay.m:
--------------------------------------------------------------------------------
1 | function target = overlay(this,west,east,south,north,varargin)
2 | %KML.OVERLAY(west, east, south, north) Places the image file (specified by the pair
3 | % attribute 'file','image.png') as a ground overlay in the kml file. The corners
4 | % of the image are given by inputs west, east, south and north.
5 | % To make the overlay transparent, change the alpha portion of the color parameter
6 | % to a different hex value - eg.: 50% transparent, use KML.OVERLAY(...,'color','80FFFFFF')
7 | %
8 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
9 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
10 |
11 | target = struct('type','','id','');
12 |
13 | [west,east,south,north] = this.checkUnit(west,east,south,north);
14 |
15 | p = inputParser;
16 |
17 | p.addRequired('west', @(a)isnumeric(a) && ~isempty(a) && numel(a)==1);
18 | p.addRequired('east', @(a)isnumeric(a) && ~isempty(a) && numel(a)==1);
19 | p.addRequired('south',@(a)isnumeric(a) && ~isempty(a) && numel(a)==1);
20 | p.addRequired('north',@(a)isnumeric(a) && ~isempty(a) && numel(a)==1);
21 |
22 | p.addParamValue('id',kml.getTempID('kml_overlay'),@ischar);
23 | p.addParamValue('name','kml_overlay',@ischar);
24 | p.addParamValue('description','',@ischar);
25 | p.addParamValue('visibility',true,@islogical);
26 | p.addParamValue('file','',@ischar);
27 | p.addParamValue('viewBoundScale',1,@(a)isnumeric(a) && numel(a)==1);
28 | p.addParamValue('color','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
29 | p.addParamValue('altitude',1,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
30 | p.addParamValue('rotation',0,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
31 | p.addParamValue('drawOrder',0,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
32 | p.addParamValue('altitudeMode','clampToGround',@(a)ismember(a,{'clampToGround','absolute'}));
33 |
34 | p.addParamValue('timeStamp','',@ischar);
35 | p.addParamValue('timeSpanBegin','',@ischar);
36 | p.addParamValue('timeSpanEnd','',@ischar);
37 |
38 | p.parse(west,east,south,north,varargin{:});
39 |
40 | arg = p.Results;
41 |
42 | if isempty(arg.file)
43 | error('Missing file parameter')
44 | end
45 |
46 | arg.rotation = this.checkUnit(arg.rotation);
47 |
48 | overlay = this.xml.createElement('GroundOverlay');
49 | llbox = this.xml.createElement('LatLonBox');
50 | icon = this.xml.createElement('Icon');
51 |
52 | overlay.setAttribute('id',arg.id);
53 | overlay.appendChild(this.textNode('name',arg.name));
54 | overlay.appendChild(this.textNode('color',arg.color));
55 | overlay.appendChild(this.textNode('visibility',num2str(arg.visibility)));
56 | overlay.appendChild(this.textNode('description',arg.description));
57 | overlay.appendChild(this.textNode('altitude',num2str(arg.altitude)));
58 | overlay.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
59 | overlay.appendChild(this.textNode('drawOrder',num2str(arg.drawOrder)));
60 |
61 | if ~isempty(arg.timeStamp)
62 | timeStamp = this.xml.createElement('TimeStamp');
63 | timeStamp.appendChild(this.textNode('when',arg.timeStamp));
64 | overlay.appendChild(timeStamp);
65 | elseif ~isempty(arg.timeSpanBegin) || ~isempty(arg.timeSpanEnd)
66 | timeSpan = this.xml.createElement('TimeSpan');
67 | if ~isempty(arg.timeSpanBegin)
68 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin));
69 | end
70 |
71 | if ~isempty(arg.timeSpanEnd)
72 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd));
73 | end
74 | overlay.appendChild(timeSpan);
75 | end
76 |
77 | llbox.appendChild(this.textNode('north', num2str(north,16)));
78 | llbox.appendChild(this.textNode('south', num2str(south,16)));
79 | llbox.appendChild(this.textNode('east', num2str(east,16)));
80 | llbox.appendChild(this.textNode('west', num2str(west,16)));
81 | llbox.appendChild(this.textNode('rotation', num2str(arg.rotation)));
82 |
83 | icon.appendChild(this.textNode('href',arg.file));
84 | icon.appendChild(this.textNode('viewBoundScale',num2str(arg.viewBoundScale)));
85 |
86 | overlay.appendChild(llbox);
87 | overlay.appendChild(icon);
88 | this.doc.appendChild(overlay);
89 |
90 | target.id = arg.id;
91 | target.type = 'GroundOverlay';
92 | this.addIncludeFile(arg.file);
93 | end
--------------------------------------------------------------------------------
/@kml/plot.m:
--------------------------------------------------------------------------------
1 | function target = plot(this,long,lat,varargin)
2 | %KML.PLOT(long,lat) Create 2D plot of long vs. lat
3 | % Similar to built-in plot function
4 | %
5 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
6 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
7 |
8 | target = struct('type','','id','');
9 |
10 | [long,lat] = this.checkUnit(long,lat);
11 |
12 | p = inputParser;
13 | nlat = numel(lat);
14 | p.addRequired('lat', @(a)isnumeric(a) && isvector(a) &&~isempty(lat));
15 | p.addRequired('long',@(a)isnumeric(a) && isvector(a) &&~isempty(lat) && numel(a)==nlat);
16 |
17 | p.addParamValue('id',kml.getTempID('kml_plot'),@ischar);
18 | p.addParamValue('name','kml_plot',@ischar);
19 | p.addParamValue('description','',@ischar);
20 | p.addParamValue('visibility',true,@islogical);
21 | p.addParamValue('lineColor','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
22 | p.addParamValue('polyColor','00FFFFFF',@(a)ischar(a) && numel(a)==8);
23 | p.addParamValue('lineWidth',1,@(a)isnumeric(a) && numel(a)==1);
24 | p.addParamValue('altitude',1,@(a)isnumeric(a) && isvector(a) &&~isempty(a));
25 | p.addParamValue('altitudeMode','clampToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
26 | p.addParamValue('extrude',false,@islogical);
27 | p.addParamValue('tessellate',true,@islogical);
28 |
29 | p.addParamValue('timeStamp','',@ischar);
30 | p.addParamValue('timeSpanBegin','',@ischar);
31 | p.addParamValue('timeSpanEnd','',@ischar);
32 |
33 | p.parse(lat,long,varargin{:});
34 |
35 | arg = p.Results;
36 |
37 | if numel(arg.altitude)~=nlat
38 | alt = repmat(arg.altitude(1),size(lat));
39 | else
40 | alt = arg.altitude;
41 | end
42 |
43 | %Create coordinate text structure
44 |
45 | % coordinates = mat2str([long(:) lat(:) alt(:)]);
46 | % coordinates = coordinates(2:end-1);
47 | % coordinates = strrep(coordinates,' ',',');
48 | % coordinates = strrep(coordinates,';',' ');
49 | coordinates = sprintf('%0.16g,%0.16g,%0.16g ',[long(:) lat(:) alt(:)].');
50 |
51 | placemark = this.xml.createElement('Placemark');
52 | linestring = this.xml.createElement('LineString');
53 | style = this.xml.createElement('Style');
54 | linestyle = this.xml.createElement('LineStyle');
55 | polystyle = this.xml.createElement('PolyStyle');
56 |
57 | placemark.setAttribute('id',arg.id);
58 | placemark.appendChild(this.textNode('name',arg.name));
59 | placemark.appendChild(this.textNode('visibility',num2str(arg.visibility)));
60 | placemark.appendChild(this.textNode('description',arg.description));
61 |
62 | if ~isempty(arg.timeStamp)
63 | timeStamp = this.xml.createElement('TimeStamp');
64 | timeStamp.appendChild(this.textNode('when',arg.timeStamp));
65 | placemark.appendChild(timeStamp);
66 | elseif ~isempty(arg.timeSpanBegin) || ~isempty(arg.timeSpanEnd)
67 | timeSpan = this.xml.createElement('TimeSpan');
68 | if ~isempty(arg.timeSpanBegin)
69 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin));
70 | end
71 |
72 | if ~isempty(arg.timeSpanEnd)
73 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd));
74 | end
75 | placemark.appendChild(timeSpan);
76 | end
77 |
78 |
79 | linestyle.appendChild(this.textNode('color',arg.lineColor));
80 | linestyle.appendChild(this.textNode('width',num2str(arg.lineWidth)));
81 |
82 | polystyle.appendChild(this.textNode('color',arg.polyColor));
83 |
84 | linestring.setAttribute('id',['LineString_' arg.id]);
85 | linestring.appendChild(this.textNode('extrude',num2str(arg.extrude)));
86 | linestring.appendChild(this.textNode('tesselate',num2str(arg.tessellate)));
87 | linestring.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
88 | linestring.appendChild(this.textNode('coordinates',coordinates));
89 |
90 | style.appendChild(linestyle);
91 | style.appendChild(polystyle);
92 | placemark.appendChild(style);
93 | placemark.appendChild(linestring);
94 | this.doc.appendChild(placemark);
95 |
96 | target.id = arg.id;
97 | target.type = 'Placemark';
98 | target.coordinates_type = 'LineString';
99 | target.coordinates_id = ['LineString_' target.id ];
100 | end
--------------------------------------------------------------------------------
/@kml/plot3.m:
--------------------------------------------------------------------------------
1 | function target = plot3(this,long,lat,alt,varargin)
2 | %KML.PLOT3(long,lat,alt) Create 3D plot of long vs. lat vs. alt
3 | % Similar to built-in plot3 function
4 | %
5 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
6 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
7 |
8 | target = struct('type','','id','');
9 |
10 | [long,lat] = this.checkUnit(long,lat);
11 |
12 | p = inputParser;
13 |
14 | nlat = numel(lat);
15 | p.addRequired('lat', @(a)isnumeric(a) && isvector(a) &&~isempty(a));
16 | p.addRequired('long',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a) == nlat);
17 | p.addRequired('alt', @(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a) == nlat);
18 |
19 | p.addParamValue('id',kml.getTempID('kml_plot3'),@ischar);
20 | p.addParamValue('name','kml_plot3',@ischar);
21 | p.addParamValue('description','',@ischar);
22 | p.addParamValue('visibility',true,@islogical);
23 | p.addParamValue('lineColor','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
24 | p.addParamValue('polyColor','00FFFFFF',@(a)ischar(a) && numel(a)==8);
25 | p.addParamValue('lineWidth',1,@(a)isnumeric(a) && numel(a)==1);
26 | p.addParamValue('altitudeMode','relativeToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
27 | p.addParamValue('extrude',false,@islogical);
28 | p.addParamValue('tessellate',true,@islogical);
29 |
30 | p.addParamValue('timeStamp','',@ischar);
31 | p.addParamValue('timeSpanBegin','',@ischar);
32 | p.addParamValue('timeSpanEnd','',@ischar);
33 |
34 | p.parse(lat,long,alt,varargin{:});
35 |
36 | arg = p.Results;
37 |
38 | if numel(lat)~=numel(long) || numel(lat)~=numel(alt)
39 | error('Invalid input size')
40 | end
41 |
42 | % coordinates = mat2str([long(:) lat(:) alt(:)]);
43 | % coordinates = coordinates(2:end-1);
44 | % coordinates = strrep(coordinates,' ',',');
45 | % coordinates = strrep(coordinates,';',' ');
46 | coordinates = sprintf('%0.16g,%0.16g,%0.16g ',[long(:) lat(:) alt(:)].');
47 |
48 | placemark = this.xml.createElement('Placemark');
49 | linestring = this.xml.createElement('LineString');
50 | style = this.xml.createElement('Style');
51 | linestyle = this.xml.createElement('LineStyle');
52 | polystyle = this.xml.createElement('PolyStyle');
53 |
54 | placemark.setAttribute('id',arg.id);
55 | placemark.appendChild(this.textNode('name',arg.name));
56 | placemark.appendChild(this.textNode('visibility',num2str(arg.visibility)));
57 | placemark.appendChild(this.textNode('description',arg.description));
58 |
59 | if ~isempty(arg.timeStamp)
60 | timeStamp = this.xml.createElement('TimeStamp');
61 | timeStamp.appendChild(this.textNode('when',arg.timeStamp));
62 | placemark.appendChild(timeStamp);
63 | elseif ~isempty(arg.timeSpanBegin) || ~isempty(arg.timeSpanEnd)
64 | timeSpan = this.xml.createElement('TimeSpan');
65 | if ~isempty(arg.timeSpanBegin)
66 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin));
67 | end
68 |
69 | if ~isempty(arg.timeSpanEnd)
70 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd));
71 | end
72 | placemark.appendChild(timeSpan);
73 | end
74 |
75 |
76 | linestyle.appendChild(this.textNode('color',arg.lineColor));
77 | linestyle.appendChild(this.textNode('width',num2str(arg.lineWidth)));
78 |
79 | polystyle.appendChild(this.textNode('color',arg.polyColor));
80 |
81 | linestring.setAttribute('id',['LineString_' arg.id]);
82 | linestring.appendChild(this.textNode('extrude',num2str(arg.extrude)));
83 | linestring.appendChild(this.textNode('tesselate',num2str(arg.tessellate)));
84 | linestring.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
85 | linestring.appendChild(this.textNode('coordinates',coordinates));
86 |
87 | style.appendChild(linestyle);
88 | style.appendChild(polystyle);
89 | placemark.appendChild(style);
90 | placemark.appendChild(linestring);
91 | this.doc.appendChild(placemark);
92 |
93 | target.id = arg.id;
94 | target.type = 'Placemark';
95 | target.coordinates_type = 'LineString';
96 | target.coordinates_id = ['LineString_' target.id ];
97 | end
--------------------------------------------------------------------------------
/@kml/point.m:
--------------------------------------------------------------------------------
1 | function target = point(this,long,lat,alt,varargin)
2 | %KML.POINT(long,lat,alt) Places point markers in the positions given by long, lat and alt
3 | % Similar to built-in scatter function. For a list of available markers, run
4 | % help kml.parseIconURL
5 | %
6 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
7 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
8 |
9 | target = struct('type','','id','');
10 |
11 | [long,lat] = this.checkUnit(long,lat);
12 |
13 | p = inputParser;
14 |
15 | nlat = numel(lat);
16 |
17 | p.addRequired('lat', @(a)isnumeric(a) && isvector(a) &&~isempty(a));
18 | p.addRequired('long',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
19 | p.addRequired('alt', @(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
20 |
21 | p.addParamValue('id',kml.getTempID('kml_point'),@ischar);
22 | p.addParamValue('name','kml_point',@ischar);
23 | p.addParamValue('description','',@ischar);
24 | p.addParamValue('visibility',true,@islogical);
25 | p.addParamValue('iconColor','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
26 | p.addParamValue('iconURL','',@ischar);
27 | p.addParamValue('iconScale',1,@(a)isnumeric(a) && (numel(a)==1 || numel(a)==nlat));
28 | p.addParamValue('labelScale',1,@(a)isnumeric(a) && numel(a)==1);
29 | p.addParamValue('labelColor','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
30 | p.addParamValue('altitudeMode','relativeToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
31 |
32 | p.addParamValue('timeStamp','',@ischar);
33 | p.addParamValue('timeSpanBegin','',@ischar);
34 | p.addParamValue('timeSpanEnd','',@ischar);
35 |
36 | p.parse(lat,long,alt,varargin{:});
37 |
38 | arg = p.Results;
39 |
40 | if ~iscell(arg.name)
41 | arg.name = {arg.name};
42 | end
43 |
44 | if nlat>1 && numel(arg.name)==1
45 | arg.name = repmat(arg.name,nlat,1);
46 | end
47 |
48 | if nlat>1 && numel(arg.visibility)==1
49 | arg.visibility = repmat(arg.visibility,nlat,1);
50 | end
51 |
52 | if nlat>1 && numel(arg.iconScale)==1
53 | arg.iconScale = repmat(arg.iconScale,nlat,1);
54 | end
55 |
56 |
57 | for i = 1:nlat
58 | target(i).type = 'Placemark';
59 | target(i).coordinates_type = 'Point';
60 | target(i).id = [arg.id '_' num2str(i)];
61 | target(i).coordinates_id = ['Point_' target(i).id ];
62 | % coordinates = mat2str([long(i) lat(i) alt(i)]);
63 | % coordinates = coordinates(2:end-1);
64 | % coordinates = strrep(coordinates,' ',',');
65 | % coordinates = strrep(coordinates,';',' ');
66 | coordinates = sprintf('%0.16g,%0.16g,%0.16g ',[long(i) lat(i) alt(i)].');
67 |
68 | placemark = this.xml.createElement('Placemark');
69 | point = this.xml.createElement('Point');
70 | style = this.xml.createElement('Style');
71 | iconstyle = this.xml.createElement('IconStyle');
72 | labelstyle = this.xml.createElement('LabelStyle');
73 | icon = this.xml.createElement('Icon');
74 |
75 | placemark.setAttribute('id',target(i).id);
76 | placemark.appendChild(this.textNode('name',arg.name{i}));
77 | placemark.appendChild(this.textNode('visibility',num2str(arg.visibility(i))));
78 | placemark.appendChild(this.textNode('description',arg.description));
79 |
80 | if ~isempty(arg.timeStamp)
81 | timeStamp = this.xml.createElement('TimeStamp');
82 | timeStamp.appendChild(this.textNode('when',arg.timeStamp));
83 | placemark.appendChild(timeStamp);
84 | elseif ~isempty(arg.timeSpanBegin) || ~isempty(arg.timeSpanEnd)
85 | timeSpan = this.xml.createElement('TimeSpan');
86 | if ~isempty(arg.timeSpanBegin)
87 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin));
88 | end
89 |
90 | if ~isempty(arg.timeSpanEnd)
91 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd));
92 | end
93 | placemark.appendChild(timeSpan);
94 | end
95 |
96 | iconstyle.appendChild(this.textNode('color',arg.iconColor));
97 | iconstyle.appendChild(this.textNode('scale',num2str(arg.iconScale(i))));
98 | icon.appendChild(this.textNode('href',kml.parseIconURL(arg.iconURL)));
99 |
100 | labelstyle.appendChild(this.textNode('color',arg.labelColor));
101 | labelstyle.appendChild(this.textNode('scale',num2str(arg.labelScale)));
102 |
103 | point.setAttribute('id',target(i).coordinates_id);
104 | point.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
105 | point.appendChild(this.textNode('coordinates',coordinates));
106 |
107 | iconstyle.appendChild(icon);
108 | style.appendChild(iconstyle);
109 | style.appendChild(labelstyle);
110 | placemark.appendChild(style);
111 | placemark.appendChild(point);
112 | this.doc.appendChild(placemark);
113 |
114 | end
115 | end
--------------------------------------------------------------------------------
/@kml/poly.m:
--------------------------------------------------------------------------------
1 | function target = poly(this,long,lat,varargin)
2 | %KML.POLY(long,lat) Draw a closed polygon with vertices given by long, lat.
3 | % To change the altitude of the polygon, use KML.POLY(...,'altitude', 10000)
4 | %
5 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
6 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
7 |
8 | p = inputParser;
9 | p.KeepUnmatched = true;
10 | p.addParamValue('altitude',1,@(a)isnumeric(a) && isvector(a) &&~isempty(a));
11 | p.parse(varargin{:});
12 |
13 | arg = p.Results;
14 |
15 | v = varargin;
16 |
17 | [tmpvar,hasAltitude ]= ismemberVarargin('altitude',v);
18 |
19 | if any(hasAltitude)
20 | v(hasAltitude+1) = [];
21 | v(hasAltitude) = [];
22 | end
23 |
24 | target = this.poly3(long,lat,ones(size(lat)).*arg.altitude,v{:});
25 | end
26 |
27 |
28 | function [tf,loc] = ismemberVarargin(a,varin)
29 | if mod(numel(varin),2)==1
30 | error('Invalid number of named arguments.')
31 | end
32 | if ~iscell(a)
33 | a = {a};
34 | end
35 | tf = false(size(a));
36 | loc = zeros(size(a));
37 | for i = 1:numel(a)
38 | for j = 1:2:numel(varin)
39 | if ischar(varin{j}) && strcmp(varin{j},a{i})
40 | tf(i) = true;
41 | loc(i) = j;
42 | end
43 | end
44 | end
45 | end
--------------------------------------------------------------------------------
/@kml/poly3.m:
--------------------------------------------------------------------------------
1 | function target = poly3(this,long,lat,alt,varargin)
2 | %KML.POLY3(long,lat,alt) Draw a polygonal 3D form, with vertices given by long, lat and alt.
3 | %
4 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
5 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
6 |
7 | target = struct('type','','id','');
8 |
9 | [long,lat] = this.checkUnit(long,lat);
10 |
11 | p = inputParser;
12 | nlat = numel(lat);
13 |
14 | p.addRequired('lat', @(a)isnumeric(a) && isvector(a) &&~isempty(a));
15 | p.addRequired('long',@(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
16 | p.addRequired('alt', @(a)isnumeric(a) && isvector(a) &&~isempty(a) && numel(a)==nlat);
17 |
18 | p.addParamValue('id',kml.getTempID('kml_poly3'),@ischar);
19 | p.addParamValue('name','kml_poly3',@ischar);
20 | p.addParamValue('description','',@ischar);
21 | p.addParamValue('visibility',true,@islogical);
22 | p.addParamValue('lineColor','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
23 | p.addParamValue('polyColor','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
24 | p.addParamValue('lineWidth',1,@(a)isnumeric(a) && numel(a)==1);
25 | p.addParamValue('altitudeMode','relativeToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
26 | p.addParamValue('extrude',false,@islogical);
27 | p.addParamValue('tessellate',true,@islogical);
28 |
29 | p.addParamValue('timeStamp','',@ischar);
30 | p.addParamValue('timeSpanBegin','',@ischar);
31 | p.addParamValue('timeSpanEnd','',@ischar);
32 |
33 | p.parse(lat,long,alt,varargin{:});
34 |
35 | arg = p.Results;
36 |
37 | % coordinates = mat2str([long(:) lat(:) alt(:)]);
38 | % coordinates = coordinates(2:end-1);
39 | % coordinates = strrep(coordinates,' ',',');
40 | % coordinates = strrep(coordinates,';',' ');
41 |
42 | coordinates = sprintf('%0.16g,%0.16g,%0.16g ',[long(:) lat(:) alt(:)].');
43 |
44 | placemark = this.xml.createElement('Placemark');
45 |
46 | polygon = this.xml.createElement('Polygon');
47 | outboundary = this.xml.createElement('outerBoundaryIs');
48 | linearring = this.xml.createElement('LinearRing');
49 | style = this.xml.createElement('Style');
50 | linestyle = this.xml.createElement('LineStyle');
51 | polystyle = this.xml.createElement('PolyStyle');
52 |
53 | placemark.setAttribute('id',arg.id);
54 | placemark.appendChild(this.textNode('name',arg.name));
55 | placemark.appendChild(this.textNode('visibility',num2str(arg.visibility)));
56 | placemark.appendChild(this.textNode('description',arg.description));
57 |
58 | if ~isempty(arg.timeStamp)
59 | timeStamp = this.xml.createElement('TimeStamp');
60 | timeStamp.appendChild(this.textNode('when',arg.timeStamp));
61 | placemark.appendChild(timeStamp);
62 | elseif ~isempty(arg.timeSpanBegin) || ~isempty(arg.timeSpanEnd)
63 | timeSpan = this.xml.createElement('TimeSpan');
64 | if ~isempty(arg.timeSpanBegin)
65 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin));
66 | end
67 |
68 | if ~isempty(arg.timeSpanEnd)
69 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd));
70 | end
71 | placemark.appendChild(timeSpan);
72 | end
73 |
74 | linestyle.appendChild(this.textNode('color',arg.lineColor));
75 | linestyle.appendChild(this.textNode('width',num2str(arg.lineWidth)));
76 |
77 | polystyle.appendChild(this.textNode('color',arg.polyColor));
78 |
79 | linearring.setAttribute('id',['LinearRing_' arg.id]);
80 | linearring.appendChild(this.textNode('coordinates',coordinates));
81 |
82 | polygon.setAttribute('id',['Polygon_' arg.id]);
83 | polygon.appendChild(this.textNode('extrude',num2str(arg.extrude)));
84 | polygon.appendChild(this.textNode('tesselate',num2str(arg.tessellate)));
85 | polygon.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
86 |
87 |
88 | outboundary.appendChild(linearring);
89 | polygon.appendChild(outboundary);
90 |
91 | style.appendChild(linestyle);
92 | style.appendChild(polystyle);
93 | placemark.appendChild(style);
94 | placemark.appendChild(polygon);
95 | this.doc.appendChild(placemark);
96 |
97 | target.type = 'Placemark';
98 | target.id = arg.id;
99 | end
--------------------------------------------------------------------------------
/@kml/polyMap.m:
--------------------------------------------------------------------------------
1 | function target = polyMap(this,long,lat,value,varargin)
2 | %KML.POLY3(long,lat,alt) Draw a polygonal 3D form, with vertices given by long, lat and alt.
3 | %
4 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
5 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
6 |
7 | target = struct('type','','id','');
8 |
9 | lat = lat(:);
10 | long = long(:);
11 | value = value(:);
12 |
13 | p = inputParser;
14 | nlat = numel(lat);
15 |
16 | p.addRequired('lat', @(a)isnumeric(a) &&~isempty(a));
17 | p.addRequired('long',@(a)isnumeric(a) &&~isempty(a) && numel(a)==nlat);
18 | p.addRequired('value', @(a)isnumeric(a) &&~isempty(a) && numel(a)==nlat);
19 |
20 | p.addParamValue('id',kml.getTempID('kml_polyMap'),@ischar);
21 | p.addParamValue('name','kml_polyMap',@ischar);
22 | p.addParamValue('description','',@ischar);
23 | p.addParamValue('visibility',true,@islogical);
24 | p.addParamValue('colorMap','jet',@ischar);
25 | p.addParamValue('scale',1e4,@(a)isnumeric(a) && numel(a)==1);
26 | p.addParamValue('width',1,@(a)isnumeric(a) && numel(a)==1);
27 | p.addParamValue('type','square',@(a)ismember(lower(a),{'square','circle'}));
28 | p.addParamValue('noFolder',false,@islogical)
29 |
30 | p.addParamValue('timeStamp','',@ischar);
31 | p.addParamValue('timeSpanBegin','',@ischar);
32 | p.addParamValue('timeSpanEnd','',@ischar);
33 |
34 | p.parse(lat,long,value,varargin{:});
35 |
36 | arg = p.Results;
37 |
38 | fDR = this.checkUnit(1);
39 |
40 | lls = max(max(lat)-min(lat),max(long)-min(long));
41 | width = 0.5*lls./sqrt(numel(value));
42 |
43 |
44 | if arg.noFolder
45 | f = this;
46 | else
47 | f = this.createFolder(arg.name);
48 | end
49 |
50 | maxVal = max(value);
51 | minVal = min(value);
52 |
53 | if maxVal==minVal
54 | minVal = 0;
55 | end
56 |
57 |
58 |
59 |
60 | scale = arg.scale .* value; %-minVal)./(maxVal-minVal);
61 |
62 | ncolors = 100;
63 | cmap = feval(arg.colorMap,ncolors);
64 | vs = linspace(minVal,maxVal,ncolors);
65 |
66 | switch lower(arg.type)
67 | case 'square'
68 | pLong = 0.5*[-1 -1 1 1 -1].*arg.width.*width;
69 | pLat = 0.5*[-1 1 1 -1 -1].*arg.width.*width;
70 | case 'circle'
71 | t = linspace(0,2*pi,100);
72 | pLong = 0.5*sin(t).*arg.width.*width;
73 | pLat = 0.5*cos(t).*arg.width.*width;
74 | end
75 |
76 | maxValCount = 1e4;
77 |
78 |
79 | if numel(value) > maxValCount
80 | warning('kml:maxPoly','Ignoring any point under the top %i values',maxValCount);
81 | [tmp,indexToPlot] = sort(-value);
82 | indexToPlot = indexToPlot(1:maxValCount).';
83 | else
84 | indexToPlot = 1:numel(value);
85 | end
86 |
87 | for i = indexToPlot
88 | if scale(i)>0
89 | color = [interp1(vs,cmap(:,1),value(i)) interp1(vs,cmap(:,2),value(i)) interp1(vs,cmap(:,3),value(i))];
90 | colorHex = kml.color2kmlHex(color);
91 | target(end+1) = f.poly3(long(i) + pLong,lat(i) + pLat.*cosd(fDR*lat(i)),ones(size(pLong)).*scale(i), ...
92 | 'extrude', true, ...
93 | 'visibility',arg.visibility,...
94 | 'altitudeMode','absolute',...
95 | 'lineWidth',0, ...
96 | 'polyColor',colorHex, ...
97 | 'id', [arg.id '_' num2str(i)]);
98 | end
99 | end
100 | target(1) = []; %remove the empty initial field
101 | end
--------------------------------------------------------------------------------
/@kml/quadoverlay.m:
--------------------------------------------------------------------------------
1 | function target = quadoverlay(this,long,lat,varargin)
2 | %KML.quadoverlay(longitude, latitude) Places the image file (specified by the pair
3 | % attribute 'file','image.png') as a ground overlay in the kml file. The corners
4 | % of the image are given by inputs longitude and latitude (which should represent 4 points).
5 | % To make the overlay transparent, change the alpha portion of the color parameter
6 | % to a different hex value - eg.: 50% transparent, use KML.OVERLAY(...,'color','80FFFFFF')
7 | %
8 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
9 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
10 |
11 | target = struct('type','','id','');
12 |
13 | [long,lat] = this.checkUnit(long,lat);
14 |
15 | p = inputParser;
16 |
17 | p.addRequired('long', @(a)isnumeric(a) && numel(a)==4);
18 | p.addRequired('lat', @(a)isnumeric(a) && numel(a)==4);
19 |
20 | p.addParamValue('id',kml.getTempID('kml_overlay'),@ischar);
21 | p.addParamValue('name','kml_overlay',@ischar);
22 | p.addParamValue('description','',@ischar);
23 | p.addParamValue('visibility',true,@islogical);
24 | p.addParamValue('file','',@ischar);
25 | p.addParamValue('viewBoundScale',1,@(a)isnumeric(a) && numel(a)==1);
26 | p.addParamValue('color','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
27 | p.addParamValue('altitude',1,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
28 | p.addParamValue('drawOrder',0,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
29 | p.addParamValue('altitudeMode','clampToGround',@(a)ismember(a,{'clampToGround','absolute'}));
30 |
31 | p.addParamValue('timeStamp','',@ischar);
32 | p.addParamValue('timeSpanBegin','',@ischar);
33 | p.addParamValue('timeSpanEnd','',@ischar);
34 |
35 | p.parse(long,lat,varargin{:});
36 |
37 | arg = p.Results;
38 |
39 | if isempty(arg.file)
40 | error('Missing file parameter')
41 | end
42 |
43 | coordinates = sprintf('%0.16g,%0.16g ',[long(:) lat(:)].');
44 |
45 | overlay = this.xml.createElement('GroundOverlay');
46 | icon = this.xml.createElement('Icon');
47 | gxLatLonQuad = this.xml.createElement('gx:LatLonQuad');
48 |
49 | overlay.setAttribute('id',arg.id);
50 | overlay.appendChild(this.textNode('name',arg.name));
51 | overlay.appendChild(this.textNode('color',arg.color));
52 | overlay.appendChild(this.textNode('visibility',num2str(arg.visibility)));
53 | overlay.appendChild(this.textNode('description',arg.description));
54 | overlay.appendChild(this.textNode('altitude',num2str(arg.altitude)));
55 | overlay.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
56 | overlay.appendChild(this.textNode('drawOrder',num2str(arg.drawOrder)));
57 |
58 | if ~isempty(arg.timeStamp)
59 | timeStamp = this.xml.createElement('TimeStamp');
60 | timeStamp.appendChild(this.textNode('when',arg.timeStamp));
61 | overlay.appendChild(timeStamp);
62 | elseif ~isempty(arg.timeSpanBegin) || ~isempty(arg.timeSpanEnd)
63 | timeSpan = this.xml.createElement('TimeSpan');
64 | if ~isempty(arg.timeSpanBegin)
65 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin));
66 | end
67 |
68 | if ~isempty(arg.timeSpanEnd)
69 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd));
70 | end
71 | overlay.appendChild(timeSpan);
72 | end
73 |
74 | gxLatLonQuad.appendChild(this.textNode('coordinates',coordinates));
75 |
76 | icon.appendChild(this.textNode('href',arg.file));
77 | icon.appendChild(this.textNode('viewBoundScale',num2str(arg.viewBoundScale)));
78 |
79 | overlay.appendChild(gxLatLonQuad);
80 | overlay.appendChild(icon);
81 | this.doc.appendChild(overlay);
82 |
83 | target.id = arg.id;
84 | target.type = 'GroundOverlay';
85 |
86 | this.addIncludeFile(arg.file);
87 | end
--------------------------------------------------------------------------------
/@kml/quiver.m:
--------------------------------------------------------------------------------
1 | function target = quiver(this,long,lat,u,v,varargin)
2 | %KML.QUIVER(long,lat,u,v) Create a quiver plot, similar to built-in
3 | % function quiver3, using line arrows.
4 | %
5 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
6 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
7 |
8 | target = struct('type','','id','','coordinates_type','','coordinates_id','');
9 |
10 | [longDEG,latDEG] = this.checkUnit(long,lat);
11 |
12 | p = inputParser;
13 |
14 | nlat = numel(lat);
15 |
16 | p.addRequired('lat', @(a)isnumeric(a) && ~isempty(a));
17 | p.addRequired('long', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
18 | p.addRequired('u', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
19 | p.addRequired('v', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
20 |
21 | p.addParamValue('altitude',1000,@(a)isnumeric(a) && numel(a)==1);
22 | p.addParamValue('scale',1,@(a)isnumeric(a) && numel(a)==1);
23 | p.addParamValue('arrowBaseSize',0.3,@(a)isnumeric(a) && numel(a)==1);
24 | p.addParamValue('plotArrows',true,@islogical);
25 | p.addParamValue('arrowHeadSize',0.3,@(a)isnumeric(a) && numel(a)==1);
26 |
27 | p.addParamValue('color','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
28 | p.addParamValue('name','kml_quiver',@ischar);
29 | p.addParamValue('id',kml.getTempID('kml_quiver'),@ischar);
30 | p.addParamValue('description','',@ischar);
31 | p.addParamValue('visibility',true,@islogical);
32 | p.addParamValue('altitudeMode','relativeToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
33 |
34 | p.addParamValue('timeStamp','',@ischar);
35 | p.addParamValue('timeSpanBegin','',@ischar);
36 | p.addParamValue('timeSpanEnd','',@ischar);
37 |
38 | p.parse(lat,long,u,v,varargin{:});
39 |
40 | arg = p.Results;
41 |
42 | f = this.createFolder(arg.name);
43 |
44 | uv = sqrt((u+v).^2);
45 |
46 | edgelen = @(a)(max(a(:))-min(a(:))).^2;
47 | dS = edgelen(latDEG) + edgelen(longDEG);
48 |
49 | scale = sqrt((u.^2 + v.^2)./dS);
50 | scale = arg.scale .* scale;
51 | alpha = arg.arrowHeadSize;
52 | beta = arg.arrowBaseSize;
53 | for i = 1:numel(lat)
54 | if arg.plotArrows
55 | long2 = scale(i).*[0 u(i) u(i)-alpha*(u(i)+beta*(v(i)+eps)) u(i) u(i)-alpha*(u(i)-beta*(v(i)+eps))] + long(i);
56 | lat2 = scale(i).*[0 v(i) v(i)-alpha*(v(i)-beta*(u(i)+eps)) v(i) v(i)-alpha*(v(i)+beta*(u(i)+eps))] + lat(i);
57 | else
58 | long2 = scale(i).*[0 u(i)] + long(i);
59 | lat2 = scale(i).*[0 v(i)] + lat(i);
60 | end
61 | target(i) = f.plot(long2,lat2, 'altitude',arg.altitude,...
62 | 'altitudeMode',arg.altitudeMode, ...
63 | 'visibility',arg.visibility, ...
64 | 'name',sprintf('Arrow %i',i), ...
65 | 'lineColor',arg.color, ...
66 | 'timeStamp', arg.timeStamp , ...
67 | 'timeSpanBegin', arg.timeSpanBegin , ...
68 | 'timeSpanEnd', arg.timeSpanEnd, ...
69 | 'id', [arg.id '_' num2str(i)] ...
70 | );
71 | end
72 | end
--------------------------------------------------------------------------------
/@kml/quiver3d.m:
--------------------------------------------------------------------------------
1 | function target = quiver3d(this,long,lat,alt,u,v,w,varargin)
2 | %KML.QUIVER3D(long,lat,alt,u,v,w) Create a quiver plot, similar to built-in
3 | % function quiver3, using 3D arrows.
4 | %
5 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
6 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
7 |
8 | target = struct('type','','id','','location_id','','orientation_id','','scale_id','','model_id','');
9 |
10 | [longDEG,latDEG] = this.checkUnit(long,lat);
11 |
12 | p = inputParser;
13 |
14 | nlat = numel(lat);
15 |
16 | p.addRequired('lat', @(a)isnumeric(a) && ~isempty(a));
17 | p.addRequired('long', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
18 | p.addRequired('alt', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
19 | p.addRequired('u', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
20 | p.addRequired('v', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
21 | p.addRequired('w', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
22 |
23 | p.addParamValue('scale',100,@(a)isnumeric(a) && numel(a)==1);
24 | p.addParamValue('color','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
25 | p.addParamValue('name','kml_quiver3D',@ischar);
26 | p.addParamValue('id',kml.getTempID('kml_quiver3D'),@ischar);
27 | p.addParamValue('description','',@ischar);
28 | p.addParamValue('visibility',true,@islogical);
29 | p.addParamValue('model','',@ischar);
30 | p.addParamValue('altitudeMode','relativeToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
31 |
32 | p.addParamValue('timeStamp','',@ischar);
33 | p.addParamValue('timeSpanBegin','',@ischar);
34 | p.addParamValue('timeSpanEnd','',@ischar);
35 |
36 | p.parse(lat,long,alt,u,v,w,varargin{:});
37 |
38 | arg = p.Results;
39 |
40 | if isempty(arg.model)
41 | arrowfile = 'arrow3d.dae';
42 |
43 | arg.model = arrowfile;
44 | end
45 |
46 | modelpath = which(arg.model);
47 |
48 | if ~isempty(modelpath)
49 | if isempty(dir(arg.model))
50 | copyfile(modelpath,arg.model);
51 | end
52 | else
53 | error('File %s not found!',arg.model);
54 | end
55 |
56 | f = this.createFolder(arg.name);
57 |
58 | uv = sqrt((u+v).^2);
59 | if strcmpi(this.unit,'deg')
60 | rad2deg = 180/pi;
61 | else
62 | rad2deg = 1;
63 | end
64 | heading = rad2deg * atan2(u,v);
65 | tilt = rad2deg * atan2(w,uv)-pi/2;
66 | roll = zeros(size(lat));
67 |
68 |
69 | edgelen = @(a)(max(a(:))-min(a(:))).^2;
70 | dS = edgelen(latDEG) + edgelen(longDEG) + edgelen(alt);
71 |
72 | scale = sqrt((u.^2 + v.^2 + w.^2)./dS);
73 | scale = arg.scale .* scale;
74 |
75 | for i = 1:numel(lat)
76 | target(i) = f.model(long(i),lat(i),alt(i),heading(i),tilt(i),roll(i), 'scale',scale(i),'model',arg.model, ...
77 | 'altitudeMode',arg.altitudeMode, ...
78 | 'visibility',arg.visibility, ...
79 | 'name',sprintf('Arrow %i',i), ...
80 | 'timeStamp', arg.timeStamp , ...
81 | 'timeSpanBegin', arg.timeSpanBegin , ...
82 | 'timeSpanEnd', arg.timeSpanEnd, ...
83 | 'id', [arg.id '_' num2str(i)] ...
84 | );
85 | end
86 |
87 | this.addIncludeFile(arg.model);
88 | end
--------------------------------------------------------------------------------
/@kml/scatter.m:
--------------------------------------------------------------------------------
1 | function target = scatter(this,long,lat,varargin)
2 | %KML.SCATTER(long,lat,alt) Places point markers in the positions given by long and lat
3 | % Similar to built-in scatter function. For a list of available markers, run
4 | % help kml.parseIconURL
5 | %
6 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
7 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
8 |
9 | target = struct('type','','id','');
10 |
11 | [long,lat] = this.checkUnit(long,lat);
12 |
13 | nlat = numel(lat);
14 |
15 | p = inputParser;
16 |
17 | p.addRequired('lat', @(a)isnumeric(a) && ~isempty(a));
18 | p.addRequired('long',@(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
19 |
20 | p.addParamValue('id',kml.getTempID('kml_scatter'),@ischar);
21 | p.addParamValue('name','kml_scatter',@ischar);
22 | p.addParamValue('description','',@ischar);
23 | p.addParamValue('visibility',true,@islogical);
24 | p.addParamValue('iconColor','FFFFFFFF',@(a)(iscell(a) && numel(a)==nlat) || (size(a,1)==1 || size(a,1)==nlat) || (ischar(a) && numel(a)==8));
25 | p.addParamValue('iconURL','',@(a)ischar(a)||(iscell(a)&&numel(a)==nlat));
26 | p.addParamValue('iconScale',1,@(a)isnumeric(a) && (numel(a)==1 || numel(a)==nlat));
27 | p.addParamValue('altitudeMode','clampToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
28 | p.addParamValue('altitude',1,@(a)isnumeric(a) && (numel(a)==1 || numel(a)==nlat));
29 |
30 | p.addParamValue('timeStamp','',@(a)ischar(a)||iscell(a));
31 | p.addParamValue('timeSpanBegin','',@(a)ischar(a)||iscell(a));
32 | p.addParamValue('timeSpanEnd','',@(a)ischar(a)||iscell(a));
33 |
34 | p.parse(lat,long,varargin{:});
35 |
36 | arg = p.Results;
37 |
38 | if numel(arg.altitude)~=nlat
39 | alt = repmat(arg.altitude(1),size(lat));
40 | else
41 | alt = arg.altitude;
42 | end
43 |
44 | nc = numel(arg.iconColor);
45 | ns = numel(arg.iconScale);
46 |
47 |
48 | if ~iscell(arg.timeStamp)
49 | arg.timeStamp = {arg.timeStamp};
50 | end
51 | if numel(arg.timeStamp)~=nlat
52 | arg.timeStamp = repmat(arg.timeStamp,nlat,1);
53 | end
54 |
55 | if ~iscell(arg.timeSpanBegin)
56 | arg.timeSpanBegin = {arg.timeSpanBegin};
57 | end
58 | if numel(arg.timeSpanBegin)~=nlat
59 | arg.timeSpanBegin = repmat(arg.timeSpanBegin,nlat,1);
60 | end
61 |
62 | if ~iscell(arg.timeSpanEnd)
63 | arg.timeSpanEnd = {arg.timeSpanEnd};
64 | end
65 | if numel(arg.timeSpanEnd)~=nlat
66 | arg.timeSpanEnd = repmat(arg.timeSpanEnd,nlat,1);
67 | end
68 |
69 | if nc~=1
70 | if ~iscell(arg.iconColor) && ~ischar(arg.iconColor)
71 | if ismember(size(arg.iconColor,2),[3 4])
72 | %Color matrix, convert to string format
73 | iC = cell(size(arg.iconColor,1),1);
74 | for i = 1:size(arg.iconColor,1)
75 | c = min(max(floor(arg.iconColor(i,:)*255),0),255);
76 | if numel(c)==3
77 | [r,g,b,a] = deal(c(1),c(2),c(3),255);
78 | else
79 | [r,g,b,a] = deal(c(1),c(2),c(3),c(4));
80 | end
81 | [rhex, ghex, bhex, ahex ]= deal(dec2hex(r),dec2hex(g),dec2hex(b),dec2hex(a));
82 | if length(rhex)==1,rhex=['0' rhex];end
83 | if length(ghex)==1,ghex=['0' ghex];end
84 | if length(bhex)==1,bhex=['0' bhex];end
85 | if length(ahex)==1,ahex=['0' ahex];end
86 |
87 | iC{i} = [ahex bhex ghex rhex];
88 | end
89 | arg.iconColor = iC;
90 | nc = numel(arg.iconColor);
91 | else
92 | error('Invalid iconColor argument')
93 | end
94 | end
95 | end
96 |
97 | iconURL = kml.parseIconURL(arg.iconURL);
98 | scatterfolder = this.xml.createElement('Folder');
99 |
100 | for i = 1:nlat
101 | target(i).id = [arg.id '_' num2str(i)];
102 | target(i).type = 'Placemark';
103 | % coordinates = mat2str([long(i) lat(i) alt(i)]);
104 | % coordinates = coordinates(2:end-1);
105 | % coordinates = strrep(coordinates,' ',',');
106 | % coordinates = strrep(coordinates,';',' ');
107 | coordinates = sprintf('%0.16g,%0.16g,%0.16g ',[long(i) lat(i) alt(i)].');
108 |
109 | placemark = this.xml.createElement('Placemark');
110 | point = this.xml.createElement('Point');
111 | style = this.xml.createElement('Style');
112 | iconstyle = this.xml.createElement('IconStyle');
113 | icon = this.xml.createElement('Icon');
114 |
115 | placemark.setAttribute('id',target(i).id);
116 | placemark.appendChild(this.textNode('name','')); %[arg.name '_' num2str(i)]
117 | placemark.appendChild(this.textNode('visibility',num2str(arg.visibility)));
118 | placemark.appendChild(this.textNode('description',arg.description));
119 |
120 | if ~isempty(arg.timeStamp{i})
121 | timeStamp = this.xml.createElement('TimeStamp');
122 | timeStamp.appendChild(this.textNode('when',arg.timeStamp{i}));
123 | placemark.appendChild(timeStamp);
124 | elseif ~isempty(arg.timeSpanBegin{i}) || ~isempty(arg.timeSpanEnd{i})
125 | timeSpan = this.xml.createElement('TimeSpan');
126 | if ~isempty(arg.timeSpanBegin{i})
127 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin{i}));
128 | end
129 |
130 | if ~isempty(arg.timeSpanEnd{i})
131 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd{i}));
132 | end
133 | placemark.appendChild(timeSpan);
134 | end
135 |
136 | if nc==nlat
137 | iconstyle.appendChild(this.textNode('color',arg.iconColor{i}));
138 | else
139 | iconstyle.appendChild(this.textNode('color',arg.iconColor));
140 | end
141 |
142 | if ns==nlat
143 | iconstyle.appendChild(this.textNode('scale',num2str(arg.iconScale(i))));
144 | else
145 | iconstyle.appendChild(this.textNode('scale',num2str(arg.iconScale)));
146 | end
147 |
148 | if iscell(iconURL)
149 | icon.appendChild(this.textNode('href',iconURL{i}));
150 | else
151 | icon.appendChild(this.textNode('href',iconURL));
152 | end
153 |
154 | point.setAttribute('id',['Point_' arg.id]);
155 | point.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
156 | point.appendChild(this.textNode('coordinates',coordinates));
157 |
158 | iconstyle.appendChild(icon);
159 | style.appendChild(iconstyle);
160 | placemark.appendChild(style);
161 | placemark.appendChild(point);
162 | scatterfolder.appendChild(placemark);
163 | end
164 |
165 | scatterfolder.appendChild(this.textNode('name',arg.name));
166 | scatterfolder.appendChild(this.textNode('id', arg.id));
167 | this.doc.appendChild(scatterfolder);
168 | end
--------------------------------------------------------------------------------
/@kml/scatter3.m:
--------------------------------------------------------------------------------
1 | function target = scatter3(this,long,lat,alt,varargin)
2 | %KML.SCATTER3(long,lat,alt) Places point markers in the positions given by long, lat and alt
3 | % Similar to built-in scatter3 function. For a list of available markers, run
4 | % help kml.parseIconURL
5 | %
6 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
7 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
8 |
9 | target = struct('type','','id','');
10 |
11 | [long,lat] = this.checkUnit(long,lat);
12 |
13 | nlat = numel(lat);
14 |
15 | p = inputParser;
16 |
17 | p.addRequired('lat', @(a)isnumeric(a) && ~isempty(a));
18 | p.addRequired('long',@(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
19 | p.addRequired('alt', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
20 |
21 | p.addParamValue('id',kml.getTempID('kml_scatter3'),@ischar);
22 | p.addParamValue('name','kml_scatter3',@ischar);
23 | p.addParamValue('description','',@ischar);
24 | p.addParamValue('visibility',true,@islogical);
25 | p.addParamValue('iconColor','FFFFFFFF',@(a)(iscell(a) && numel(a)==nlat) || (size(a,1)==1 || size(a,1)==nlat) || (ischar(a) && numel(a)==8));
26 | p.addParamValue('iconURL','',@(a)ischar(a)||(iscell(a)&&numel(a)==nlat));
27 | p.addParamValue('iconScale',1,@(a)isnumeric(a) && (numel(a)==1 || numel(a)==nlat));
28 | p.addParamValue('altitudeMode','relativeToGround',@(a)ismember(a,{'clampToGround','relativeToGround','absolute'}));
29 |
30 | p.addParamValue('timeStamp','',@(a)ischar(a)||iscell(a));
31 | p.addParamValue('timeSpanBegin','',@(a)ischar(a)||iscell(a));
32 | p.addParamValue('timeSpanEnd','',@(a)ischar(a)||iscell(a));
33 |
34 | p.parse(lat,long,alt,varargin{:});
35 |
36 | arg = p.Results;
37 |
38 |
39 | nc = numel(arg.iconColor);
40 | ns = numel(arg.iconScale);
41 |
42 | if ~iscell(arg.timeStamp)
43 | arg.timeStamp = {arg.timeStamp};
44 | end
45 | if numel(arg.timeStamp)~=nlat
46 | arg.timeStamp = repmat(arg.timeStamp,nlat,1);
47 | end
48 |
49 | if ~iscell(arg.timeSpanBegin)
50 | arg.timeSpanBegin = {arg.timeSpanBegin};
51 | end
52 | if numel(arg.timeSpanBegin)~=nlat
53 | arg.timeSpanBegin = repmat(arg.timeSpanBegin,nlat,1);
54 | end
55 | if ~iscell(arg.timeSpanEnd)
56 | arg.timeSpanEnd = {arg.timeSpanEnd};
57 | end
58 | if numel(arg.timeSpanEnd)~=nlat
59 | arg.timeSpanEnd = repmat(arg.timeSpanEnd,nlat,1);
60 | end
61 |
62 |
63 | if nc~=1
64 | if ~iscell(arg.iconColor) && ~ischar(arg.iconColor)
65 | if ismember(size(arg.iconColor,2),[3 4])
66 | %Color matrix, convert to string format
67 | iC = cell(size(arg.iconColor,1),1);
68 | for i = 1:size(arg.iconColor,1)
69 | c = min(max(floor(arg.iconColor(i,:)*255),0),255);
70 | if numel(c)==3
71 | [r,g,b,a] = deal(c(1),c(2),c(3),255);
72 | else
73 | [r,g,b,a] = deal(c(1),c(2),c(3),c(4));
74 | end
75 | [rhex, ghex, bhex, ahex ]= deal(dec2hex(r),dec2hex(g),dec2hex(b),dec2hex(a));
76 | if length(rhex)==1,rhex=['0' rhex];end
77 | if length(ghex)==1,ghex=['0' ghex];end
78 | if length(bhex)==1,bhex=['0' bhex];end
79 | if length(ahex)==1,ahex=['0' ahex];end
80 |
81 | iC{i} = [ahex bhex ghex rhex];
82 | end
83 | arg.iconColor = iC;
84 | nc = numel(arg.iconColor);
85 | else
86 | error('Invalid iconColor argument')
87 | end
88 | end
89 | end
90 |
91 | iconURL = kml.parseIconURL(arg.iconURL);
92 | scatterfolder = this.xml.createElement('Folder');
93 |
94 | for i = 1:nlat
95 | target(i).id = [arg.id '_' num2str(i)];
96 | target(i).type = 'Placemark';
97 | % coordinates = mat2str([long(i) lat(i) alt(i)]);
98 | % coordinates = coordinates(2:end-1);
99 | % coordinates = strrep(coordinates,' ',',');
100 | % coordinates = strrep(coordinates,';',' ');
101 | coordinates = sprintf('%0.16g,%0.16g,%0.16g ',[long(i) lat(i) alt(i)].');
102 |
103 | placemark = this.xml.createElement('Placemark');
104 | point = this.xml.createElement('Point');
105 | style = this.xml.createElement('Style');
106 | iconstyle = this.xml.createElement('IconStyle');
107 | icon = this.xml.createElement('Icon');
108 |
109 | placemark.setAttribute('id',target(i).id );
110 | placemark.appendChild(this.textNode('name','')); %[arg.name '_' num2str(i)]
111 | placemark.appendChild(this.textNode('visibility',num2str(arg.visibility)));
112 | placemark.appendChild(this.textNode('description',arg.description));
113 |
114 | if ~isempty(arg.timeStamp{i})
115 | timeStamp = this.xml.createElement('TimeStamp');
116 | timeStamp.appendChild(this.textNode('when',arg.timeStamp{i}));
117 | placemark.appendChild(timeStamp);
118 | elseif ~isempty(arg.timeSpanBegin{i}) || ~isempty(arg.timeSpanEnd{i})
119 | timeSpan = this.xml.createElement('TimeSpan');
120 | if ~isempty(arg.timeSpanBegin{i})
121 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin{i}));
122 | end
123 |
124 | if ~isempty(arg.timeSpanEnd{i})
125 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd{i}));
126 | end
127 | placemark.appendChild(timeSpan);
128 | end
129 |
130 | if iscell(arg.iconColor) && nc==nlat
131 | iconstyle.appendChild(this.textNode('color',arg.iconColor{i}));
132 | else
133 | iconstyle.appendChild(this.textNode('color',arg.iconColor));
134 | end
135 |
136 | if ns==nlat
137 | iconstyle.appendChild(this.textNode('scale',num2str(arg.iconScale(i))));
138 | else
139 | iconstyle.appendChild(this.textNode('scale',num2str(arg.iconScale)));
140 | end
141 |
142 | if iscell(iconURL)
143 | icon.appendChild(this.textNode('href',iconURL{i}));
144 | else
145 | icon.appendChild(this.textNode('href',iconURL));
146 | end
147 |
148 | point.setAttribute('id',['Point_' arg.id]);
149 | point.appendChild(this.textNode('altitudeMode',arg.altitudeMode));
150 | point.appendChild(this.textNode('coordinates',coordinates));
151 |
152 | iconstyle.appendChild(icon);
153 | style.appendChild(iconstyle);
154 | placemark.appendChild(style);
155 | placemark.appendChild(point);
156 | scatterfolder.appendChild(placemark);
157 | end
158 |
159 | scatterfolder.appendChild(this.textNode('name',arg.name));
160 | scatterfolder.appendChild(this.textNode('id', arg.id));
161 | this.doc.appendChild(scatterfolder);
162 | end
--------------------------------------------------------------------------------
/@kml/screenoverlay.m:
--------------------------------------------------------------------------------
1 | function target = screenoverlay(this,overlayXY,screenXY,sz,varargin)
2 | %KML.SCREENOVERLAY(overlayXY,screenXY,sz) Places the image file (specified by the pair
3 | % attribute 'file','image.png') as a screen overlay in the kml file.
4 | % Check https://developers.google.com/kml/documentation/kmlreference#screenoverlay for more info.
5 | % To make the overlay transparent, change the alpha portion of the color parameter
6 | % to a different hex value - eg.: 50% transparent, use KML.OVERLAY(...,'color','80FFFFFF')
7 | %
8 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
9 | % $Revision: 2.4 $ $Date: 2012/12/07 08:00:00 $
10 |
11 | target = struct('type','','id','');
12 |
13 |
14 |
15 | p = inputParser;
16 |
17 | p.addRequired('overlayXY', @(a)isnumeric(a) && ~isempty(a) && numel(a)==2);
18 | p.addRequired('screenXY', @(a)isnumeric(a) && ~isempty(a) && numel(a)==2);
19 | p.addRequired('sz',@(a)isnumeric(a) && ~isempty(a) && numel(a)==2);
20 |
21 | p.addParamValue('id',kml.getTempID('kml_overlay'),@ischar);
22 | p.addParamValue('name','kml_overlay',@ischar);
23 | p.addParamValue('description','',@ischar);
24 | p.addParamValue('visibility',true,@islogical);
25 | p.addParamValue('file','',@ischar);
26 | p.addParamValue('viewBoundScale',1,@(a)isnumeric(a) && numel(a)==1);
27 | p.addParamValue('color','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
28 | p.addParamValue('altitude',1,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
29 | p.addParamValue('rotation',0,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
30 | p.addParamValue('drawOrder',0,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
31 | p.addParamValue('altitudeMode','clampToGround',@(a)ismember(a,{'clampToGround','absolute'}));
32 | p.addParamValue('units','fraction',@(a)ismember(a,{'fraction','pixels','insetPixels'}));
33 |
34 | p.addParamValue('timeStamp','',@ischar);
35 | p.addParamValue('timeSpanBegin','',@ischar);
36 | p.addParamValue('timeSpanEnd','',@ischar);
37 |
38 | p.parse(overlayXY,screenXY,sz,varargin{:});
39 |
40 | arg = p.Results;
41 |
42 | if isempty(arg.file)
43 | error('Missing file parameter')
44 | end
45 |
46 | arg.rotation = this.checkUnit(arg.rotation);
47 |
48 | arg.overlayPos = overlayXY;
49 | arg.screenPos = screenXY;
50 | arg.sz = sz;
51 |
52 | %
53 | % Simple crosshairs
54 | % This screen overlay uses fractional positioning
55 | % to put the image in the exact center of the screen
56 | %
57 | % http://myserver/myimage.jpg
58 | %
59 | %
60 | %
61 | % 39.37878630116985
62 | %
63 | %
64 |
65 |
66 | %%
67 |
68 | overlay = this.xml.createElement('ScreenOverlay');
69 | overlayXY = this.xml.createElement('overlayXY');
70 | screenXY = this.xml.createElement('screenXY');
71 | size = this.xml.createElement('size');
72 | icon = this.xml.createElement('Icon');
73 |
74 | overlay.setAttribute('id',arg.id);
75 | overlay.appendChild(this.textNode('name',arg.name));
76 | overlay.appendChild(this.textNode('open','1'));
77 | overlay.appendChild(this.textNode('visibility',num2str(arg.visibility)));
78 | overlay.appendChild(this.textNode('description',arg.description));
79 | overlay.appendChild(this.textNode('drawOrder',num2str(arg.drawOrder)));
80 | overlay.appendChild(this.textNode('color',arg.color));
81 |
82 | if ~isempty(arg.timeStamp)
83 | timeStamp = this.xml.createElement('TimeStamp');
84 | timeStamp.appendChild(this.textNode('when',arg.timeStamp));
85 | overlay.appendChild(timeStamp);
86 | elseif ~isempty(arg.timeSpanBegin) || ~isempty(arg.timeSpanEnd)
87 | timeSpan = this.xml.createElement('TimeSpan');
88 | if ~isempty(arg.timeSpanBegin)
89 | timeSpan.appendChild(this.textNode('begin',arg.timeSpanBegin));
90 | end
91 |
92 | if ~isempty(arg.timeSpanEnd)
93 | timeSpan.appendChild(this.textNode('end',arg.timeSpanEnd));
94 | end
95 | overlay.appendChild(timeSpan);
96 | end
97 |
98 | overlayXY.setAttribute('x',num2str(arg.overlayPos(1),16))
99 | overlayXY.setAttribute('y',num2str(arg.overlayPos(2),16))
100 | overlayXY.setAttribute('xunits','fraction')
101 | overlayXY.setAttribute('yunits','fraction')
102 |
103 | screenXY.setAttribute('x',num2str(arg.screenPos(1),16))
104 | screenXY.setAttribute('y',num2str(arg.screenPos(2),16))
105 | screenXY.setAttribute('xunits','fraction')
106 | screenXY.setAttribute('yunits','fraction')
107 |
108 | size.setAttribute('x',num2str(arg.sz(1)))
109 | size.setAttribute('y',num2str(arg.sz(2)))
110 | size.setAttribute('xunits','fraction')
111 | size.setAttribute('yunits','fraction')
112 | overlay.appendChild(this.textNode('rotation', num2str(arg.rotation)));
113 |
114 | icon.appendChild(this.textNode('href',arg.file));
115 |
116 | overlay.appendChild(overlayXY);
117 | overlay.appendChild(screenXY);
118 | overlay.appendChild(size);
119 | overlay.appendChild(icon);
120 |
121 | this.doc.appendChild(overlay);
122 |
123 | target.id = arg.id;
124 | target.type = 'ScreenOverlay';
125 | this.addIncludeFile(arg.file);
126 | end
--------------------------------------------------------------------------------
/@kml/surf.m:
--------------------------------------------------------------------------------
1 | function target = surf(this,long,lat,alt,cval ,varargin)
2 | %KML.surf(long,lat,alt) Create a surface contour of alt in a grid defined by long and lat.
3 | % Similar to built-in surf function
4 | %
5 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
6 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
7 |
8 | target = struct('type','','id','');
9 |
10 | p = inputParser;
11 |
12 | [long,lat] = this.checkUnit(long,lat);
13 |
14 |
15 | nlat = numel(lat);
16 | [r,c] = size(lat);
17 | p.addRequired('lat', @(a)isnumeric(a) && ~isempty(a));
18 | p.addRequired('long', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
19 | p.addRequired('alt', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
20 | p.addRequired('cval', @(a)isnumeric(a) && ~isempty(a) && numel(a)==nlat);
21 |
22 | p.addParamValue('name','kml_surf',@ischar);
23 | p.addParamValue('id',kml.getTempID('kml_surf'),@ischar);
24 | p.addParamValue('description','',@ischar);
25 | p.addParamValue('visibility',true,@islogical);
26 | p.addParamValue('colorMap','jet',@ischar);
27 | p.addParamValue('color','',@(a)ischar(a) && numel(a)==8);
28 |
29 | p.addParamValue('timeStamp','',@ischar);
30 | p.addParamValue('timeSpanBegin','',@ischar);
31 | p.addParamValue('timeSpanEnd','',@ischar);
32 |
33 | p.parse(lat,long,alt,cval,varargin{:});
34 |
35 | arg = p.Results;
36 | arg.visibility = num2str(arg.visibility);
37 |
38 | if isempty(arg.color)
39 | lineColor = 'FF000000';
40 | else
41 | lineColor = '00000000'; %arg.color;
42 | end
43 |
44 |
45 | f = this.createFolder(arg.name);
46 |
47 | ncolors = 100;
48 | cmap = feval(arg.colorMap,ncolors);
49 | cspace = 1:ncolors;
50 | aspace = linspace(min(cval(:)),max(cval(:)),ncolors);
51 | for i = 2:r
52 | for j = 2:c
53 | longC = [long(i-1,j-1) long(i,j-1) long(i,j) long(i-1,j-1)];% long(i-1,j) long(i,j) long(i-1,j-1)];
54 | latC = [lat(i-1,j-1) lat(i,j-1) lat(i,j) lat(i-1,j-1)];% lat(i-1,j) lat(i,j) lat(i-1,j-1)];
55 | altC = [alt(i-1,j-1) alt(i,j-1) alt(i,j) alt(i-1,j-1)];% alt(i-1,j) alt(i,j) alt(i-1,j-1)];
56 |
57 | alev = mean([cval(i-1,j-1) cval(i,j-1) cval(i,j)]);
58 | iC = round(interp1(aspace,cspace,alev,'linear',1));
59 | color = cmap(iC ,:);
60 |
61 | if isempty(arg.color)
62 | colorHex = kml.color2kmlHex(color);
63 | else
64 | colorHex = arg.color;
65 | end
66 |
67 |
68 | % f.poly3(longC,latC,altC, 'polyColor', colorHex, ...
69 | % 'lineColor','FF000000',... %['00' colorHex(3:end)],...
70 | % 'altitudeMode','relativeToGround', ...
71 | % 'visibility',arg.visibility, ...
72 | % 'name',sprintf('Cell (%i,%i)',i,j), ...
73 | % 'timeStamp', arg.timeStamp , ...
74 | % 'timeSpanBegin', arg.timeSpanBegin , ...
75 | % 'timeSpanEnd', arg.timeSpanEnd ...
76 | % );
77 |
78 | target(end+1).id = fastPoly(longC,latC,altC,sprintf('Cell (%i,%i)',i,j),[arg.id '_' sprintf('Cell (%i,%i)',i,j)]);
79 | target(end).type = 'Placemark';
80 |
81 | longC = [long(i-1,j-1) long(i-1,j) long(i,j) long(i-1,j-1)];
82 | latC = [lat(i-1,j-1) lat(i-1,j) lat(i,j) lat(i-1,j-1)];
83 | altC = [alt(i-1,j-1) alt(i-1,j) alt(i,j) alt(i-1,j-1)];
84 |
85 | alev = mean([cval(i-1,j-1) cval(i-1,j) cval(i,j)]);
86 | iC = round(interp1(aspace,cspace,alev,'linear',1));
87 | color = cmap(iC ,:);
88 |
89 | if isempty(arg.color)
90 | colorHex = kml.color2kmlHex(color);
91 | else
92 | colorHex = arg.color;
93 | end
94 |
95 |
96 | % f.poly3(longC,latC,altC, 'polyColor', colorHex, ...
97 | % 'lineColor',lineColor,... %['00' colorHex(3:end)],...
98 | % 'altitudeMode','relativeToGround', ...
99 | % 'visibility',arg.visibility, ...
100 | % 'name',sprintf('Cell (%i,%i)',i,j), ...
101 | % 'timeStamp', arg.timeStamp , ...
102 | % 'timeSpanBegin', arg.timeSpanBegin , ...
103 | % 'timeSpanEnd', arg.timeSpanEnd ...
104 | % );
105 | %
106 |
107 | target(end+1).id = fastPoly(longC,latC,altC,sprintf('Cell 2 (%i,%i)',i,j),[arg.id '_' sprintf('Cell (%i,%i)',i,j)]);
108 | target(end).type = 'Placemark';
109 | end
110 | end
111 |
112 |
113 | function id = fastPoly(long,lat,alt,name,id)
114 |
115 | extrudeNode = this.textNode('extrude','0');
116 | tessellateNode = this.textNode('tesselate','1');
117 | altitudeModeNode = this.textNode('altitudeMode','absolute');
118 | visibilityNode = this.textNode('visibility',arg.visibility);
119 | widthNode = this.textNode('width','1');
120 | lineColorNode = this.textNode('color',lineColor);
121 |
122 | coordinates = sprintf('%0.16g,%0.16g,%0.16g ',[long(:) lat(:) alt(:)].');
123 |
124 | placemark = this.xml.createElement('Placemark');
125 |
126 | polygon = this.xml.createElement('Polygon');
127 | outboundary = this.xml.createElement('outerBoundaryIs');
128 | linearring = this.xml.createElement('LinearRing');
129 | style = this.xml.createElement('Style');
130 | linestyle = this.xml.createElement('LineStyle');
131 | polystyle = this.xml.createElement('PolyStyle');
132 |
133 | placemark.setAttribute('id',id);
134 | placemark.appendChild(this.textNode('name',name));
135 | placemark.appendChild(visibilityNode);
136 |
137 | linestyle.appendChild(lineColorNode);
138 | linestyle.appendChild(widthNode);
139 |
140 | polystyle.appendChild(this.textNode('color',colorHex));
141 |
142 | linearring.setAttribute('id','LinearRing');
143 | linearring.appendChild(this.textNode('coordinates',coordinates));
144 |
145 | polygon.setAttribute('id','Polygon');
146 | polygon.appendChild(extrudeNode);
147 | polygon.appendChild(tessellateNode);
148 | polygon.appendChild(altitudeModeNode);
149 |
150 | outboundary.appendChild(linearring);
151 | polygon.appendChild(outboundary);
152 |
153 | style.appendChild(linestyle);
154 | style.appendChild(polystyle);
155 | placemark.appendChild(style);
156 | placemark.appendChild(polygon);
157 | f.doc.appendChild(placemark);
158 | end
159 | end
--------------------------------------------------------------------------------
/@kml/text.m:
--------------------------------------------------------------------------------
1 | function target = text(this,long,lat,alt,txt,varargin)
2 | %KML.TEXT(long,lat,alt,txt) Writes the text given by txt at the coordinates
3 | % given by long, lat and alt. To write in more than one coordinate, pass an
4 | % array of coordinates, and a cell of texts, with the same number of members.
5 | %
6 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
7 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
8 |
9 | % target = struct('type','','id','');
10 |
11 | if ~iscell(txt)
12 | txt = {txt};
13 | end
14 |
15 | nlat = numel(lat);
16 |
17 | if ~(numel(long)==nlat && numel(alt)==nlat && numel(txt)==nlat)
18 | error('Invalid input sizes')
19 | end
20 |
21 | v = varargin;
22 |
23 | [tmpvar,hasIconURL ]= ismemberVarargin('iconURL',v);
24 | [tmpvar,hasIconScale ]= ismemberVarargin('iconScale',v);
25 |
26 | if any(hasIconURL)
27 | v{hasIconURL+1} = 'none';
28 | else
29 | v{end+1} = 'iconURL';
30 | v{end+1} = 'none';
31 | end
32 |
33 | if any(hasIconScale)
34 | v{hasIconScale+1} = 0;
35 | else
36 | v{end+1} = 'IconScale';
37 | v{end+1} = 0;
38 | end
39 |
40 | for i = 1:numel(lat)
41 | target(i) = this.point(long(i),lat(i),alt(i),'name',txt{i},v{:});
42 | end
43 |
44 | end
45 |
46 | function [tf,loc] = ismemberVarargin(a,varin)
47 | if mod(numel(varin),2)==1
48 | error('Invalid number of named arguments.')
49 | end
50 | if ~iscell(a)
51 | a = {a};
52 | end
53 | tf = false(size(a));
54 | loc = zeros(size(a));
55 | for i = 1:numel(a)
56 | for j = 1:2:numel(varin)
57 | if ischar(varin{j}) && strcmp(varin{j},a{i})
58 | tf(i) = true;
59 | loc(i) = j;
60 | end
61 | end
62 | end
63 | end
--------------------------------------------------------------------------------
/@kml/transfer.m:
--------------------------------------------------------------------------------
1 | function target = transfer(this,axisHandle,varargin)
2 | %KML.TRANSFER(ax) Transfer the axis from the handle ax to the KML as an overlay.
3 | % Example:
4 | % k = kml;
5 | % t = linspace(0,2*pi,1000);
6 | % figure;
7 | % plot(t,sin(t));
8 | % k.transfer(gca)
9 | % k.run
10 | %
11 | % The corners of the overlay are taken from the axis limits.
12 | %
13 | % Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero)
14 | % $Revision: 2.3 $ $Date: 2012/09/05 08:00:00 $
15 |
16 | p = inputParser;
17 |
18 | p.addRequired('axisHandle', @(a)ishghandle(a) && strcmpi(get(a,'Type'),'axes'));
19 |
20 | p.addParamValue('transparentBG',true,@islogical);
21 | p.addParamValue('keepAxis',false,@islogical);
22 | p.addParamValue('inPlace',false,@islogical);
23 | p.addParamValue('blurRadius',0,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
24 | p.addParamValue('blurSigma',1,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
25 | p.addParamValue('resizeFactor',1,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
26 |
27 | p.addParamValue('id',kml.getTempID('kml_overlay'),@ischar);
28 | p.addParamValue('name','kml_overlay',@ischar);
29 | p.addParamValue('description','',@ischar);
30 | p.addParamValue('visibility',true,@islogical);
31 | p.addParamValue('viewBoundScale',1,@(a)isnumeric(a) && numel(a)==1);
32 | p.addParamValue('color','FFFFFFFF',@(a)ischar(a) && numel(a)==8);
33 | p.addParamValue('altitude',1,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
34 | p.addParamValue('rotation',0,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
35 | p.addParamValue('drawOrder',0,@(a)isnumeric(a) &&~isempty(a) && numel(a)==1);
36 | p.addParamValue('altitudeMode','clampToGround',@(a)ismember(a,{'clampToGround','absolute'}));
37 |
38 | p.addParamValue('timeStamp','',@ischar);
39 | p.addParamValue('timeSpanBegin','',@ischar);
40 | p.addParamValue('timeSpanEnd','',@ischar);
41 |
42 | p.parse(axisHandle,varargin{:});
43 |
44 | arg = p.Results;
45 |
46 |
47 | xlim = get(axisHandle,'XLim');
48 | ylim = get(axisHandle,'YLim');
49 |
50 | f = ancestor(axisHandle,'Figure');
51 | name = get(f,'Name');
52 |
53 | if isempty(name)
54 | if isnumeric(f)
55 | name = sprintf('Figure %i',f);
56 | else
57 | [tmpvar,name] = fileparts(tempname(pwd));
58 | end
59 | end
60 |
61 | basename = name;
62 |
63 | name = [name '.png'];
64 | k = 1;
65 | while ~isempty(dir(name))
66 | name = sprintf('%s (%i)%s',basename,k,'.png');
67 | k = k+1;
68 | end
69 |
70 | if ~arg.inPlace
71 | ftmp = figure;
72 | axtmp = copyobj(axisHandle,ftmp);
73 | set(ftmp,'ColorMap',get(f,'ColorMap'));
74 | set(ftmp,'Position',get(0,'ScreenSize'));
75 | else
76 | axtmp = axisHandle;
77 | ftmp = ancestor(axtmp,'figure');
78 | end
79 |
80 | [west,east,south,north] = deal(xlim(1),xlim(2),ylim(1),ylim(2));
81 | if ~arg.keepAxis
82 | axis(axtmp,'off')
83 |
84 | set(axtmp,'XTick',[],'YTick',[],'ZTick',[])
85 | set(get(axtmp,'XLabel'),'Visible','off');
86 | set(get(axtmp,'YLabel'),'Visible','off');
87 | set(get(axtmp,'ZLabel'),'Visible','off');
88 |
89 | tightInset = get(axtmp, 'TightInset');
90 | position(1) = tightInset(1);
91 | position(2) = tightInset(2);
92 | position(3) = 1 - tightInset(1) - tightInset(3);
93 | position(4) = 1 - tightInset(2) - tightInset(4);
94 | set(axtmp, 'Position', position);
95 | else
96 | p = get(axtmp, 'Position');
97 |
98 | longSpan = abs(west-east);
99 | latSpan = abs(south-north);
100 | west = west - (longSpan/p(3)) *p(1);
101 | east = east + (longSpan/p(3))*(1-p(3)-p(1));
102 | south = south - (latSpan/p(4))*p(2);
103 | north = north + (latSpan/p(4))*(1-p(4)-p(2));
104 | end
105 |
106 | saveas(ftmp, name);
107 |
108 | %Remove a line of 3 pixels that MATLAB adds when saving the figure...
109 | %MUST CHECK if this holds always or not
110 | im = imread(name);
111 | im = im(1:end-3,1:end-3,:);
112 |
113 | if arg.blurRadius > 0 && arg.resizeFactor~=1
114 | im = resize(im,ceil(size(im)*arg.resizeFactor));
115 | end
116 |
117 |
118 | if arg.transparentBG
119 | axc = get(axtmp,'Color');
120 | axc = ceil(axc*255);
121 | alphaMap = uint8(~(im(:,:,1)==axc(1) & im(:,:,2)==axc(2) & im(:,:,3)==axc(3))*255);
122 |
123 | if arg.blurRadius > 0
124 | im = blur(im,arg.blurRadius,arg.blurSigma);
125 | alphaMap = blur(alphaMap,arg.blurRadius,arg.blurSigma);
126 | end
127 | imwrite(im,name,'Alpha',alphaMap);
128 | else
129 | if arg.blurRadius > 0
130 | im = blur(im,arg.blurRadius,arg.blurSigma);
131 | end
132 | imwrite(im,name);
133 | end
134 |
135 | target = this.overlay(west,east,south,north,'file',name,...
136 | 'id',arg.id,...
137 | 'name',arg.name,...
138 | 'description',arg.description,...
139 | 'visibility',arg.visibility,...
140 | 'viewBoundScale',arg.viewBoundScale,...
141 | 'color',arg.color,...
142 | 'altitude',arg.altitude,...
143 | 'rotation',arg.rotation,...
144 | 'drawOrder',arg.drawOrder,...
145 | 'altitudeMode',arg.altitudeMode,...
146 | 'timeStamp', arg.timeStamp ,...
147 | 'timeSpanBegin', arg.timeSpanBegin ,...
148 | 'timeSpanEnd', arg.timeSpanEnd ...
149 | );
150 |
151 | close(ftmp);
152 |
153 | this.addIncludeFile(name);
154 | end
155 |
156 |
157 | function im = blur(im,radius,sigma)
158 | im = double(im)./255;
159 | BR = ceil(radius);
160 | N = 2*BR+1;
161 | kernel = zeros(N);
162 | dist = sqrt(repmat((1:N) - BR-1,N,1).^2 + repmat((1:N).' - BR-1,1,N).^2);
163 | kernel = (1/(2*pi*sigma*sigma)) .* exp(-dist./(2*sigma*sigma));
164 | kernel = kernel./sum(kernel(:));
165 | if ndims(im)==3
166 | im(:,:,1) = convn(im(:,:,1),kernel,'same');
167 | im(:,:,2) = convn(im(:,:,2),kernel,'same');
168 | im(:,:,3) = convn(im(:,:,3),kernel,'same');
169 | else
170 | im= convn(im,kernel,'same');
171 | end
172 | im = uint8(im*255);
173 | end
174 |
175 |
176 | function imN = resize(im,s)
177 | if ndims(im)==3
178 | imN(:,:,1) = resize(im(:,:,1),s);
179 | imN(:,:,2) = resize(im(:,:,2),s);
180 | imN(:,:,3) = resize(im(:,:,3),s);
181 | return
182 | else
183 | im = double(im)./255;
184 | [m,n] = size(im);
185 | [mN,nN] = deal(s(1),s(2));
186 | [Y,X] = meshgrid( (0:n-1)/(n-1), (0:m-1)/(m-1) );
187 | [YI,XI] = meshgrid( (0:nN-1)/(nN-1), (0:mN-1)/(mN-1) );
188 | imN = interp2(Y, X, im, YI, XI ,'cubic');
189 | end
190 | imN = uint8(imN*255);
191 | end
--------------------------------------------------------------------------------
/README.m:
--------------------------------------------------------------------------------
1 | if isempty(which('kml'))
2 | disp(repmat('_',1,80))
3 | disp(' _ ____ __ _ _____ _ _ ')
4 | disp(' | |/ / \/ | | |_ _|__ ___| | |__ _____ __')
5 | disp(' | '' <| |\/| | |__ | |/ _ \/ _ \ | ''_ \/ _ \ \ /')
6 | disp(' |_|\_\_| |_|____| |_|\___/\___/_|_.__/\___/_\_\')
7 | disp(sprintf('\n'));
8 | disp(' Thanks for downloading the KML toolbox v1.4!');
9 | disp(sprintf('\n'));
10 | disp('For some cool examples on how to use the KML toolbox,');
11 | disp(sprintf('please check the file RunTests.m located in the folder %s',pwd));
12 | disp(repmat('_',1,80));
13 | else
14 | tmp = getpref('kmltoolbox','ShowDisclaimer',true);
15 | setpref('kmltoolbox','ShowDisclaimer',true);
16 | display(kml);
17 | setpref('kmltoolbox','ShowDisclaimer',tmp);
18 | end
--------------------------------------------------------------------------------
/html/help_clear.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_clear.jpg
--------------------------------------------------------------------------------
/html/help_clear_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_clear_01.jpg
--------------------------------------------------------------------------------
/html/help_clear_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_clear_02.jpg
--------------------------------------------------------------------------------
/html/help_contour.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_contour.jpg
--------------------------------------------------------------------------------
/html/help_contour3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_contour3.jpg
--------------------------------------------------------------------------------
/html/help_contour3_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_contour3_01.jpg
--------------------------------------------------------------------------------
/html/help_contour_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_contour_01.jpg
--------------------------------------------------------------------------------
/html/help_kml.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_kml.jpg
--------------------------------------------------------------------------------
/html/help_kml_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_kml_01.jpg
--------------------------------------------------------------------------------
/html/help_model.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_model.jpg
--------------------------------------------------------------------------------
/html/help_modelTour.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_modelTour.jpg
--------------------------------------------------------------------------------
/html/help_modelTour_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_modelTour_01.jpg
--------------------------------------------------------------------------------
/html/help_model_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_model_01.jpg
--------------------------------------------------------------------------------
/html/help_overlay.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_overlay.jpg
--------------------------------------------------------------------------------
/html/help_overlay_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_overlay_01.jpg
--------------------------------------------------------------------------------
/html/help_plot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_plot.jpg
--------------------------------------------------------------------------------
/html/help_plot3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_plot3.jpg
--------------------------------------------------------------------------------
/html/help_plot3_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_plot3_01.jpg
--------------------------------------------------------------------------------
/html/help_plot_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_plot_01.jpg
--------------------------------------------------------------------------------
/html/help_point.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_point.jpg
--------------------------------------------------------------------------------
/html/help_point_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_point_01.jpg
--------------------------------------------------------------------------------
/html/help_poly.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_poly.jpg
--------------------------------------------------------------------------------
/html/help_poly3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_poly3.jpg
--------------------------------------------------------------------------------
/html/help_poly3_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_poly3_01.jpg
--------------------------------------------------------------------------------
/html/help_poly_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_poly_01.jpg
--------------------------------------------------------------------------------
/html/help_quiver.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_quiver.jpg
--------------------------------------------------------------------------------
/html/help_quiver3d.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_quiver3d.jpg
--------------------------------------------------------------------------------
/html/help_quiver3d_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_quiver3d_01.jpg
--------------------------------------------------------------------------------
/html/help_quiver_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_quiver_01.jpg
--------------------------------------------------------------------------------
/html/help_run.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_run.jpg
--------------------------------------------------------------------------------
/html/help_run_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_run_01.jpg
--------------------------------------------------------------------------------
/html/help_scatter.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_scatter.jpg
--------------------------------------------------------------------------------
/html/help_scatter3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_scatter3.jpg
--------------------------------------------------------------------------------
/html/help_scatter3_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_scatter3_01.jpg
--------------------------------------------------------------------------------
/html/help_scatter_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_scatter_01.jpg
--------------------------------------------------------------------------------
/html/help_text.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_text.jpg
--------------------------------------------------------------------------------
/html/help_text_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_text_01.jpg
--------------------------------------------------------------------------------
/html/help_transfer.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_transfer.jpg
--------------------------------------------------------------------------------
/html/help_transfer_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_transfer_01.jpg
--------------------------------------------------------------------------------
/html/help_transfer_02.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_transfer_02.jpg
--------------------------------------------------------------------------------
/html/help_transfer_03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_transfer_03.jpg
--------------------------------------------------------------------------------
/html/help_useDegrees.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_useDegrees.jpg
--------------------------------------------------------------------------------
/html/help_useDegrees_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_useDegrees_01.jpg
--------------------------------------------------------------------------------
/html/help_useRadians.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_useRadians.jpg
--------------------------------------------------------------------------------
/html/help_useRadians_01.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/help_useRadians_01.jpg
--------------------------------------------------------------------------------
/html/helpsearch/_t.cfs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/helpsearch/_t.cfs
--------------------------------------------------------------------------------
/html/helpsearch/deletable:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/html/helpsearch/segments:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/helpsearch/segments
--------------------------------------------------------------------------------
/html/helptoc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | KML Toolbox
5 | Useful functions
6 | kml.run
7 | kml.save
8 | kml.viewKML
9 | kml.clear
10 | kml.createFolder
11 | kml.useDegrees
12 | kml.useRadians
13 | Icons alias for the markers
14 |
15 | Plotting functions
16 | kml.plot
17 | kml.plot3
18 | kml.point
19 | kml.text
20 | kml.scatter
21 | kml.scatter3
22 | kml.contour
23 | kml.contour3
24 | kml.poly
25 | kml.poly3
26 | kml.overlay
27 | kml.transfer
28 | kml.model
29 | kml.modelTour
30 | kml.quiver
31 | kml.quiver3d
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/html/info.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 14
4 | KML toolbox
5 | toolbox
6 | ./kmltoolbox.png
7 | ./
8 |
9 |
10 |
11 |
12 |
13 | Help
14 | doc kml
15 | $toolbox/matlab/icons/book_mat.gif
16 |
17 |
18 |
19 | Demos
20 | edit RunTests.m
21 | $toolbox/matlab/icons/demoicon.gif
22 |
23 |
24 |
25 | Product Page (Web)
26 | web http://www.mathworks.com/matlabcentral/fileexchange/34694-kml-toolbox-plot-anything-to-google-earth -browser;
27 | $toolbox/matlab/icons/webicon.gif
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/html/kml.clear.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | kml.clear kml.clear Clears the current kml file, removing any previous plots
Contents Syntax k = kml('kml title here');
66 | --- any plot code here
67 | k.clear;
68 | --- new plot code here Description kml.clear will delete any plot inside the current kml object, leaving it empty for future use. It will not delete any temporary file created on disk, such as images, nor will remove any .kml file previously saved.
Example
69 | k = kml('my kml file' );
70 |
71 |
72 | t = linspace(0,360,1000);
73 | k.plot(20*t, 30*cosd(t/2));
74 | k.run;
75 |
76 |
77 | k.clear;
78 |
79 |
80 | k.plot(30*t, 90*cosd(t/2));
81 | k.run;
82 | This is the first plot
83 | This is the second plot after clearing the kml object
84 | This file is part of the kml toolbox. Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero )
--------------------------------------------------------------------------------
/html/kml.contents.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | Welcome to the KML Toolbox! Welcome to the KML Toolbox! _ ____ __ _ _____ _ _
66 | | |/ / \/ | | |_ _|__ ___| | |__ _____ __
67 | | ' <| |\/| | |__ | |/ _ \/ _ \ | '_ \/ _ \ \ /
68 | |_|\_\_| |_|____| |_|\___/\___/_|_.__/\___/_\_\ Contents
Thanks for downloading the KML toolbox!
For some cool examples on how to use the KML toolbox, please check the file RunTests.m located in the folder kmltoolbox\help
This class-based toolbox allows you to create many different plots in Google Earth, by automatically creating the required xml-based kml files without any complicated user interaction.
With it, you can create:
line plots, scatter plots 2D and 3D contours 2D and 3D polygons quiver plots write text in a given point place and animate 3D models overlay images transfer more complex figures as images create nested folders to classify and aggregate your plots If you enjoy it, just drop me an email at <mailto:kml@rafael.aero kml@rafael.aero > saying for what you're using it :-)
To learn how to create an instance of the kml toolbox, check here first
Useful functions kml.run
kml.save
kml.viewKML
kml.clear
kml.createFolder
kml.useDegrees
kml.useRadians
Icons alias for the markers
Plotting functions kml.plot
kml.plot3
kml.point
kml.text
kml.scatter
kml.scatter3
kml.contour
kml.contour3
kml.poly
kml.poly3
kml.overlay
kml.transfer
kml.model
kml.modelTour
kml.quiver
kml.quiver3d
This file is part of the kml toolbox. Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero )
--------------------------------------------------------------------------------
/html/kml.contour.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | kml.contour kml.contour Create a contour of altitude in a grid defined by longitude and latitude. Similar to the built-in contour function.
Contents Syntax kml.contour(long, lat, alt)
66 | kml.contour(...,'PropertyName',PropertyValue,...) Description Creates a flat contour plot of altitude in a grid defined by longitude vs. latitude, similar to the built-in contour function.
The units for latitude and longitude are normally given in degrees, but this can be changed by calling: kml.useDegrees; or kml.useRadians; before plotting.
It is possible to fine tune the contour properties using name-value pairs:
kml.contour(...,'PropertyName',PropertyValue,...)
Properties
67 |
68 | Property Name Type Description
69 | 'name' string Name of the plot inside the kml file
70 | 'description' string A short description of what the plot represents
71 | 'visibility' true/false Control the initial visibility of the plot
72 | 'colorMap' string name of a valid colormap function Defines in which colormap the contour will be plotted. Example of valid inputs: 'jet', 'hsv', 'hot', 'cool', 'spring', 'summer', 'autumn', 'winter', 'gray', 'bone', 'copper', 'pink'
73 | 'numberOfLevels' double or 'auto' Defines number of levels in which the altitude input should be split into. Valid inputs are either the desired number of levels or 'auto'
74 | 'altitude' double Altitude where the 2D line should be plotted. Input in meters
75 | 'altitudeMode' string Choose if the altitude value is absolute to the earth model, relative to the ground level, or should be clamped to the ground. Valid inputs: 'absolute', 'relativeToGround', 'clampToGround'
76 | 'timeStamp' kml date string Associates the contour to a moment in time. Should not be used together with timeSpan. Should be a string in the XML time format (more information available here )
77 | 'timeSpanBegin' kml date string Defines the moment in time where the contour starts to exist. Should not be used together with timeStamp. Should be a string in the XML time format (more information available here )
78 | 'timeSpanEnd' kml date string Defines the moment in time where the contour finishes to exist. Should not be used together with timeStamp. Should be a string in the XML time format (more information available here )
79 |
80 |
Example
81 | k = kml('my kml file' );
82 |
83 |
84 | [x,y,z] = peaks(200);
85 | k.contour(180*x/3,90*y/3,z,'numberOfLevels' ,40);
86 |
87 |
88 | k.run;
89 |
90 | This is the result of running this example:
91 | This file is part of the kml toolbox. Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero )
--------------------------------------------------------------------------------
/html/kml.contour3.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | kml.contour3 kml.contour3 Create a 3D contour of altitude in a grid defined by longitude and latitude. Similar to the built-in contour3 function.
Contents Syntax kml.contour3(long, lat, alt)
66 | kml.contour3(...,'PropertyName',PropertyValue,...) Description Creates a 3D contour plot of altitude in a grid defined by longitude vs. latitude, similar to the built-in contour3 function, in the sense that the contours are placed at their corresponding altitude level.
The units for latitude and longitude are normally given in degrees, but this can be changed by calling: kml.useDegrees; or kml.useRadians; before plotting. Altitude is always given in meters.
It is possible to fine tune the contour3 properties using name-value pairs:
kml.contour3(...,'PropertyName',PropertyValue,...)
Properties
67 |
68 | Property Name Type Description
69 | 'name' string Name of the plot inside the kml file
70 | 'description' string A short description of what the plot represents
71 | 'visibility' true/false Control the initial visibility of the plot
72 | 'colorMap' string name of a valid colormap function Defines in which colormap the contour will be plotted. Example of valid inputs: 'jet', 'hsv', 'hot', 'cool', 'spring', 'summer', 'autumn', 'winter', 'gray', 'bone', 'copper', 'pink'
73 | 'numberOfLevels' double or 'auto' Defines number of levels in which the altitude input should be split into. Valid inputs are either the desired number of levels or 'auto'
74 | 'altitudeMode' string Choose if the altitude value is absolute to the earth model, relative to the ground level, or should be clamped to the ground. Valid inputs: 'absolute', 'relativeToGround', 'clampToGround'
75 | 'timeStamp' kml date string Associates the contour to a moment in time. Should not be used together with timeSpan. Should be a string in the XML time format (more information available here )
76 | 'timeSpanBegin' kml date string Defines the moment in time where the contour starts to exist. Should not be used together with timeStamp. Should be a string in the XML time format (more information available here )
77 | 'timeSpanEnd' kml date string Defines the moment in time where the contour finishes to exist. Should not be used together with timeStamp. Should be a string in the XML time format (more information available here )
78 |
79 |
Example
80 | k = kml('my kml file' );
81 |
82 |
83 | [x,y,z] = peaks(200);
84 | k.contour3(180*x/3,90*y/3,1e5*z+1e4,'numberOfLevels' ,40,'altitudeMode' ,'absolute' );
85 |
86 |
87 | k.run;
88 |
89 | This is the result of running this example:
90 | This file is part of the kml toolbox. Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero )
--------------------------------------------------------------------------------
/html/kml.createFolder.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | kml.createFolder kml.createFolder Create a folder inside the current kml file
Contents Syntax k = kml('kml title here');
66 | folder = k.createFolder('folder title here')
67 | --- any plot code here, using e.g. folder.plot(...)
68 | k.run; Description folder = kml.createFolder('title') creates a folder inside the current kml object. It is also possible to create nested folders, by using the same method in the folder object.
To plot inside a folder, simple use any available functions from the kml toolbox, as in:
folder.plot(...) , folder.scatter(...) , folder.model(...) , etc...
Example
69 | k = kml('my kml file' );
70 |
71 |
72 | for i = 1:10
73 | mainFolder = k.createFolder(sprintf('Folder %i' , i));
74 | for j = 1:10
75 | nestedFolder = mainFolder.createFolder(sprintf('Nested Folder %i' , j));
76 | end
77 | end
78 |
79 |
80 | k.run;
81 | This example creates a nested folder structure like this:
This file is part of the kml toolbox. Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero )
--------------------------------------------------------------------------------
/html/kml.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | kml kml Creates an instance of the kml toolbox, providing access to all its functionality.
Contents Syntax k = kml('title'); Description k = kml creates an instance of the kml toolbox, from which any of the available plots can be created. This class-based toolbox allows you to create many different plots in Google Earth, by automatically creating the required xml-based kml files without user interaction. With it, you can create:
line plots, scatter plots 2D and 3D contours 2D and 3D polygons quiver plots write text in a given point place 3D models overlay images transfer more complex figures as images folders, subfolders,... to aggregate and categorize plots If you enjoy it, just drop me an email at kml@rafael.aero saying for what you're using it :).
Example
66 | k = kml('my kml file' );
67 |
68 |
69 | t = linspace(0,360,1000);
70 | k.plot(30*t, 90*cosd(t/2));
71 |
72 |
73 | k.run;
74 |
75 | This is the result of running this example:
76 | This file is part of the kml toolbox. Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero )
--------------------------------------------------------------------------------
/html/kml.quiver3d.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | kml.quiver3d kml.quiver3d Creates a quiver plot using 3D arrows, in the coordinates defined by longitude, latitude and altitude, and arrow sizes given by the speeds u, v and w. Similar to the built-in quiver3 function.
Contents Syntax kml.quiver3d(longitude, latitude, altitude, u, v, w)
66 | kml.quiver3d(...,'PropertyName',PropertyValue,...) Description Creates a quiver plot using 3D arrows, such as the one supplied with the toolbox (arrow2d.dae). The arrows are created in the coordinates defined by longitude, latitude and altitude, and are scaled using the speeds u, v and w, and the size of the grid.
It is possible to use a different arrow model with the property pair 'model', 'modelfile.dae'
The units for the angular values are normally given in degrees, but this can be changed by calling: kml.useDegrees; or kml.useRadians; before plotting. Altitude is always given in meters.
It is possible to fine tune the point properties using name-value pairs:
kml.quiver3d(...,'PropertyName',PropertyValue,...)
Properties
67 |
68 | Property Name Type Description
69 | 'model' string Path to a different 3D model file representing an arrow.
70 | 'name' string Name of the quiver plot inside the kml file
71 | 'description' string A short description of what the quiver plot represents
72 | 'visibility' true/false Control the initial visibility of the quiver plot
73 | 'scale' double Defines a scale factor to be applied to the whole quiver plot
74 | 'altitudeMode' string Choose if the altitude value is absolute to the earth model, relative to the ground level, or should be clamped to the ground. Valid inputs: 'absolute', 'relativeToGround', 'clampToGround'
75 | 'timeStamp' kml date string Associates the quiver plot to a moment in time. Should not be used together with timeSpan. Should be a string in the XML time format (more information available here )
76 | 'timeSpanBegin' kml date string Defines the moment in time where the quiver plot starts to exist. Should not be used together with timeStamp. Should be a string in the XML time format (more information available here )
77 | 'timeSpanEnd' kml date string Defines the moment in time where the quiver plot finishes to exist. Should not be used together with timeStamp. Should be a string in the XML time format (more information available here )
78 |
79 |
Example
80 | k = kml('my kml file' );
81 |
82 |
83 | [x,y] = meshgrid(-2:.2:2,-1:.15:1);
84 | z = x .* exp(-x.^2 - y.^2);
85 | [px,py] = gradient(z,.2,.15);
86 |
87 | k.quiver3d(10*x,10*y,1e5+x*0,1000*px,1000*py,-cosd(x)*1e2,'scale' ,1500)
88 |
89 |
90 | k.run;
91 |
92 | This is the result of running this example:
93 | This file is part of the kml toolbox. Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero )
--------------------------------------------------------------------------------
/html/kml.run.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | kml.run kml.run Save and run the current kml file, opening it in the default kml viewer.
Contents Syntax k = kml('kml title here');
66 | --- any plot code here
67 | k.run; Description kml.run will save the kml file and open it in the default kml viewer. Normally, this means it will open the file in Google Earth. It can be downloaded at http://earth.google.com
Example
68 | k = kml('my kml file' );
69 |
70 |
71 | t = linspace(0,360,1000);
72 | k.plot(30*t, 90*cosd(t/2));
73 |
74 |
75 | k.run;
76 |
77 | This is the result of running this example:
78 | This file is part of the kml toolbox. Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero )
--------------------------------------------------------------------------------
/html/kml.text.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | kml.text kml.text Places text in the coordinates defined by longitude, latitude and altitude.
Contents Syntax kml.text(long, lat, alt, txt)
66 | kml.text(...,'PropertyName',PropertyValue,...) Description Places text in the coordinates defined by the inputs longitude, latitude and altitude. To place more than one text, pass an array of coordinates, and a cell array of texts.
The units for latitude and longitude are normally given in degrees, but this can be changed by calling: kml.useDegrees; or kml.useRadians; before plotting. Altitude is always given in meters.
It is possible to fine tune the text properties using name-value pairs:
kml.text(...,'PropertyName',PropertyValue,...)
Properties
67 |
68 | Property Name Type Description
69 | 'name' string Name of the text plot inside the kml file
70 | 'id' string Internal id of this text plot inside the kml
71 | 'description' string A short description of what the text plot represents
72 | 'visibility' true/false Control the initial visibility of the text plot
73 | 'altitudeMode' string Choose if the altitude value is absolute to the earth model, relative to the ground level, or should be clamped to the ground. Valid inputs: 'absolute', 'relativeToGround', 'clampToGround'
74 | 'labelScale' double Defines the size of the text. Can be one input for all markers, or an array with the same size as Latitude and Longitude, with the size of each marker
75 | 'timeStamp' kml date string Associates the text plot to a moment in time. Should not be used together with timeSpan. Should be a string in the XML time format (more information available here )
76 | 'timeSpanBegin' kml date string Defines the moment in time where the text plot starts to exist. Should not be used together with timeStamp. Should be a string in the XML time format (more information available here )
77 | 'timeSpanEnd' kml date string Defines the moment in time where the text plot finishes to exist. Should not be used together with timeStamp. Should be a string in the XML time format (more information available here )
78 |
79 |
Example
80 | k = kml('my kml file' );
81 |
82 |
83 | f = k.createFolder('Coordinates' );
84 | for lat = -80:20:80
85 | for long = -180:20:170
86 | f.text(long,lat,1e5,sprintf('Lat %g° Long %g°' ,lat,long),'labelScale' ,3)
87 | end
88 | end
89 |
90 |
91 | k.run;
92 |
93 | This is the result of running this example:
94 | This file is part of the kml toolbox. Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero )
--------------------------------------------------------------------------------
/html/kml.useDegrees.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | kml.useDegrees kml.useDegrees Switch the current kml object to accept angular inputs in degrees.
Contents Syntax kml.useDegrees; Description kml.useDegrees tells the current kml object to start accepting angular inputs in degrees, such as latitude, longitude, roll, heading and tilt. It must be used before any other plot, as it will not affect plots created before using kml.useDegrees
This is the default behavior.
Example
66 | k = kml('my kml file' );
67 |
68 |
69 | k.useDegrees;
70 |
71 |
72 | t = linspace(0,360,1000);
73 | k.plot(30*t, 90*cosd(t/2));
74 |
75 |
76 | k.run;
77 |
78 | This is the result of running this example:
79 | This file is part of the kml toolbox. Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero )
--------------------------------------------------------------------------------
/html/kml.useRadians.html:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 | kml.useRadians kml.useRadians Switch the current kml object to accept angular inputs in radians.
Contents Syntax kml.useRadians; Description kml.useRadians tells the current kml object to start accepting angular inputs in radians, such as latitude, longitude, roll, heading and tilt. It must be used before any other plot, as it will not affect plots created before using kml.useRadians
Example
66 | k = kml('my kml file' );
67 |
68 |
69 | k.useRadians;
70 |
71 |
72 | t = linspace(0,2*pi,1000);
73 | k.plot(30*t, pi/2*cos(t/2));
74 |
75 |
76 | k.run;
77 |
78 | This is the result of running this example:
79 | This file is part of the kml toolbox. Copyright 2012 Rafael Fernandes de Oliveira (rafael@rafael.aero )
--------------------------------------------------------------------------------
/html/kmldoc.m:
--------------------------------------------------------------------------------
1 | function kmldoc(topic)
2 | if nargin==0 || isempty(topic)
3 | topic = 'kml.contents';
4 | end
5 | if length(topic) > 2 && ischar(topic) && strcmpi(topic(1:3),'kml')
6 | html = [topic '.html'];
7 | htmlFile = which(html);
8 | % Display the results.
9 | if isempty(htmlFile)
10 | error('"%s.html" not found, check the instalation of your KML toolbox.',topic);
11 | else
12 | web(htmlFile,'-helpbrowser');
13 | end
14 | else
15 | doc(topic);
16 | end
17 | end
--------------------------------------------------------------------------------
/html/kmltoolbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/kmltoolbox.png
--------------------------------------------------------------------------------
/html/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/logo.png
--------------------------------------------------------------------------------
/html/nestedFolders.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/html/nestedFolders.png
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012-2014, Rafael Fernandes de Oliveira
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are
6 | met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | * Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in
12 | the documentation and/or other materials provided with the distribution
13 | * Neither the name of the copyright holder nor the names of its contributors
14 | may be used to endorse or promote products derived from this software
15 | without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 | POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/test/RunTestTour.m:
--------------------------------------------------------------------------------
1 | k = kml('Model Tour');
2 | f = k.createFolder('Above');
3 | t = linspace(0,4*pi,1000);
4 | long = cos(t)*20;
5 | lat = sin(t)*20;
6 | alt = 100000 + 0.*t;
7 |
8 | heading = 360-mod((t+pi)*180/pi,720);
9 | tilt = 0.*t;
10 | roll = 0.*t -20;
11 | f.modelTour(t*1,long,lat,alt,heading,tilt,roll,'model',fullfile(fileparts(mfilename('fullpath')),'A320.dae'),'scale',10000,'cameraMode','above','cameraDistance',1e7)
12 |
13 | f = k.createFolder('Behind');
14 | f.modelTour(t,long,lat,alt,heading,tilt,roll,'model',fullfile(fileparts(mfilename('fullpath')),'A320.dae'),'scale',100,'cameraMode','behind','cameraDistance',1e5)
15 |
16 | k.run;
--------------------------------------------------------------------------------
/test/RunTests.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/test/RunTests.m
--------------------------------------------------------------------------------
/test/RunTestsRadians.m:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/test/RunTestsRadians.m
--------------------------------------------------------------------------------
/test/bitslice.m:
--------------------------------------------------------------------------------
1 | function b = bitslice(a,lowbit,highbit)
2 | %BITSLICE(A,LOWBIT,HIGHBIT)
3 |
4 | numbits = highbit - lowbit + 1;
5 | b = bitshift(a,-lowbit);
6 | b = fix(b);
7 | b = bitand(b,bitcmp(0,numbits));
8 | b = b/max(b(:));
--------------------------------------------------------------------------------
/test/cities.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/test/cities.mat
--------------------------------------------------------------------------------
/test/logoFEx2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theolivenbaum/kml-toolbox/37e5b7a7bdcf8fff5eeb1820a7c43414318f92be/test/logoFEx2.png
--------------------------------------------------------------------------------
/test/testAnim.m:
--------------------------------------------------------------------------------
1 | time = linspace(0,4*pi,1000);
2 | longitude = cos(time)*1;
3 | latitude = sin(time)*1;
4 | altitude = 1e3 + 0.*time;
5 |
6 | yaw = 360-mod((time)*180/pi,720);
7 | gamma = 0.*time;
8 | roll = 0.*time -20;
9 |
10 | k = kml('testAnimation');
11 | k.useDegrees;
12 |
13 | N = numel(longitude);
14 |
15 | yaw = yaw - 180; %This is to correct the mis-orientation in the A320 model, you can ignore this for other models - or fix the model
16 | modelA320 = k.model(longitude(1),latitude(1),altitude(1),yaw(1),gamma(1),roll(1),'model','A320.dae','scale',10);
17 | anim = k.newAnimation('Flight');
18 |
19 | time = time.*100;
20 |
21 | for i = 2:N
22 | dT = time(i) - time(i-1);
23 | anim.updateLocation(modelA320,dT,longitude(i),latitude(i),altitude(i));
24 | anim.updateOrientation(modelA320,dT,yaw(i),gamma(i),roll(i));
25 |
26 | anim.flyToLookAt(dT, longitude(i), latitude(i),1e4)
27 | end
28 |
29 | anim.flyToLookAt(10, mean(longitude),mean(latitude),1e5);
30 |
31 | k.run;
32 |
--------------------------------------------------------------------------------