diff --git a/Claudio_Maggioni_5/Claudio_Maggioni_5.md b/Claudio_Maggioni_5/Claudio_Maggioni_5.md index 9305b98..31262e4 100644 --- a/Claudio_Maggioni_5/Claudio_Maggioni_5.md +++ b/Claudio_Maggioni_5/Claudio_Maggioni_5.md @@ -13,7 +13,6 @@ header-includes: - \usepackage{float} - \floatplacement{figure}{H} - \hypersetup{colorlinks=true,linkcolor=blue} - --- \maketitle @@ -93,40 +92,40 @@ $$ A x=b, A^{T} \lambda+s=c,(x, s)>0\right\} \end{array} $$ -A central path $\mathcal{C}$ is defined as an arc strictly composed of feasible -points which is parametrized by a scalar $\tau>0$ where each point -$\left(x_{\tau}, \lambda_{\tau}, s_{\tau}\right) \in \mathcal{C}$ satisfies the -following conditions: +The definition of the central path $\mathcal{C}$ is an arc, strictly composed of +feasible points. The path is parametrized by a scalar $\tau>0$ where each point +in the path $\left(x_{\tau}, \lambda_{\tau}, s_{\tau}\right) \in \mathcal{C}$ +satisfies the following conditions: $$ \begin{array}{c} A^{T} \lambda+s=c \\ A x=b \\ -x_{i} s_{i}=\tau \quad i=1,2, \ldots, n \\ +x_{i} s_{i}=\tau > 0 \quad i=1,2, \ldots, n \\ (x, s)>0 \end{array} $$ -We can observe how these conditions are very much similar to the KKT conditions -and, in fact, they only differ by the factor $\tau$ and by requiring the -pairwise products to be strictly greater than zero. With this, we can define the -central path as follows: +These conditions are very similar to the KKT conditions, differning only +by the factor $\tau$ and by requiring the pairwise products to be strictly +greater than zero. With this, we can define the central path as follows: $$ \mathcal{C}=\left\{\left(x_{\tau}, \lambda_{\tau}, s_{\tau}\right) \mid \tau>0\right\} $$ -Given these definitions, we can also observe that, as $\tau$ approaches zero, -the conditions we have defined become a closer and closer approximation to the -original KKT conditions. Therefore, if the central path $\mathcal{C}$ converges -to anything as $\tau$ approaches zero, then we know that it will converge to a -solution of the linear program. Meaning that the central path is leading us to a -solution by maintaining $x$ and $s$ positive while reducing the pairwise -products to zero at the same time. Usually, the Newton method is used to take -steps following $\mathcal{C}$ rather than by following the set of feasible -points $\mathcal{F}$ because it allows for longer steps before violating the -positivity constraint. +We can then observe that as $\tau$ approaches 0, the set of conditions defined +above get closer and closer to the true KKT conditions. Therefore, if the +central path C converges to anything then $\tau$ approaches zero, therefore +leading the path to the constrained minimizer while keeping $x$ and $s$ +positive but at the same time minimizing their pairwise products to zero. + +In practice, most central path implementation use Newton steps toward points on +$\mathcal{C}$ for which $\tau > 0$, rather than pure Newton steps for $F$. This +is usually possible since those newton steps are biased to stay in the +hyperspace region where $x > 0$ and $s > 0$ even without enforcing these +constraints. # Exercise 2 @@ -139,22 +138,6 @@ below: ## Exercise 2.2 - - According to Nocedal, a vector $x$ is a basic feasible point if it is in the feasible region and if there exists a subset $\beta$ of the index set $1, 2, \ldots, n$ such that: @@ -172,35 +155,14 @@ proven property to manually solve the constrained minimization problem presented in this section by aiding us with the graphical plot of the feasible region in figure \ref{fig:a}. - - ## Exercise 2.3 Since the geometrical interpretation of the definition of basic feasible point states that these point are non-other than the vertices of the feasible region, we first look at the plot above and to these points (i.e. the vertices of the -bright green non-trasparent region). Then, we look which constraint boundaries cross these -edges, and we formulate an algebraic expression to find these points. In -clockwise order, we have: +bright green non-trasparent region). Then, we look which constraint boundaries +cross these edges, and we formulate an algebraic expression to find these +points. In clockwise order, we have: - The lower-left point at the origin, given by the boundaries of the constraints $x_1 \geq 0$ and $x_2 \geq 0$: diff --git a/Claudio_Maggioni_5/Claudio_Maggioni_5.pdf b/Claudio_Maggioni_5/Claudio_Maggioni_5.pdf index c0a065a..e795b23 100644 Binary files a/Claudio_Maggioni_5/Claudio_Maggioni_5.pdf and b/Claudio_Maggioni_5/Claudio_Maggioni_5.pdf differ diff --git a/Claudio_Maggioni_5/hatchfill.m b/Claudio_Maggioni_5/hatchfill.m deleted file mode 100644 index 325e60a..0000000 --- a/Claudio_Maggioni_5/hatchfill.m +++ /dev/null @@ -1,967 +0,0 @@ -function H = hatchfill(A,varargin) -% HATCHFILL2 Hatching and speckling of patch objects -% HATCHFILL2(A) fills the patch(es) with handle(s) A. A can be a vector -% of handles or a single handle. If A is a vector, then all objects of A -% should be part of the same group for predictable results. The hatch -% consists of black lines angled at 45 degrees at 40 hatching lines over -% the axis span with no color filling between the lines. -% -% A can be handles of patch or hggroup containing patch objects for -% Pre-R2014b release. For HG2 releases, 'bar' and 'contour' objects are -% also supported. -% -% Hatching line object is actively formatted. If A, axes, or figure size -% is modified, the hatching line object will be updated accordingly to -% maintain the specified style. -% -% HATCHFILL2(A,STYL) applies STYL pattern with default paramters. STYL -% options are: -% 'single' single lines (the default) -% 'cross' double-crossed hatch -% 'speckle' speckling inside the patch boundary -% 'outspeckle' speckling outside the boundary -% 'fill' no hatching -% -% HATCHFILL2(A,STYL,Option1Name,Option1Value,...) to customize the -% hatching pattern -% -% Name Description -% -------------------------------------------------------------------- -% HatchStyle Hatching pattern (same effect as STYL argument) -% HatchAngle Angle of hatch lines in degrees (45) -% HatchDensity Number of hatch lines between axis limits -% HatchOffset Offset hatch lines in pixels (0) -% HatchColor Color of the hatch lines, 'auto' sets it to the -% EdgeColor of A -% HatchLineStyle Hatch line style -% HatchLineWidth Hatch line width -% SpeckleWidth Width of speckling region in pixels (7) -% SpeckleDensity Density of speckle points (1) -% SpeckleMarkerStyle Speckle marker style -% SpeckleFillColor Speckle fill color -% HatchVisible [{'auto'}|'on'|'off'] sets visibility of the hatch -% lines. If 'auto', Visibile option is synced to -% underlying patch object -% HatchSpacing (Deprecated) Spacing of hatch lines (5) -% -% In addition, name/value pairs of any properties of A can be specified -% -% H = HATCHFILL2(...) returns handles to the line objects comprising the -% hatch/speckle. -% -% Examples: -% Gray region with hatching: -% hh = hatchfill2(a,'cross','HatchAngle',45,'HatchSpacing',5,'FaceColor',[0.5 0.5 0.5]); -% -% Speckled region: -% hatchfill2(a,'speckle','HatchAngle',7,'HatchSpacing',1); -% Copyright 2015-2018 Takeshi Ikuma -% History: -% rev. 7 : (01-10-2018) -% * Added support for 3D faces -% * Removed HatchSpacing option -% * Added HatchDensity option -% * Hatching is no longer defined w.r.t. pixels. HatchDensity is defined -% as the number of hatch lines across an axis limit. As a result, -% HatchAngle no longer is the actual hatch angle though it should be -% close. -% * [known bug] Speckle hatching style is not working -% rev. 6 : (07-17-2016) -% * Fixed contours object hatching behavior, introduced in rev.5 -% * Added ContourStyle option to enable fast drawing if contour is convex -% rev. 5 : (05-12-2016) -% * Fixed Contour with NaN data point disappearnace issue -% * Improved contours object support -% rev. 4 : (11-18-2015) -% * Worked around the issue with HG2 contours with Fill='off'. -% * Removed nagging warning "UseHG2 will be removed..." in R2015b -% rev. 3 : (10-29-2015) -% * Added support for HG2 AREA -% * Fixed for HatchColor 'auto' error when HG2 EdgeColor is 'flat' -% * Fixed listener creation error -% rev. 2 : (10-24-2015) -% * Added New option: HatchVisible, SpeckleDensity, SpeckleWidth -% (SpeckleDensity and SpeckleWidtha are separated from HatchSpacing and -% HatchAngle, respectively) -% rev. 1 : (10-20-2015) -% * Fixed HG2 contour data extraction bug (was using wrong hidden data) -% * Fixed HG2 contour color extraction bug -% * A few cosmetic changes here and there -% rev. - : (10-19-2015) original release -% * This work is based on Neil Tandon's hatchfill submission -% (http://www.mathworks.com/matlabcentral/fileexchange/30733) -% and borrowed code therein from R. Pawlowicz, K. Pankratov, and -% Iram Weinstein. -narginchk(1,inf); -[A,opts,props] = parse_input(A,varargin); -drawnow % make sure the base objects are already drawn -if verLessThan('matlab','8.4') - H = cell(1,numel(A)); -else - H = repmat({matlab.graphics.GraphicsPlaceholder},1,numel(A)); -end -for n = 1:numel(A) - H{n} = newhatch(A(n),opts,props); - - % if legend of A(n) is shown, add hatching to it as well - % leg = handle(legend(ancestor(A,'axes'))); - % hsrc = [leg.EntryContainer.Children.Object]; - % hlc = leg.EntryContainer.Children(find(hsrc==A(n),1)); - % if ~isempty(hlc) - % hlc = hlc.Children(1); % LegendIcon object - % get(hlc.Children(1)) - % end -end -if nargout==0 - clear H -else - H = [H{:}]; - if numel(H)==numel(A) - H = reshape(H,size(A)); - else - H = H(:); - end -end -end -function H = newhatch(A,opts,props) -% 0. retrieve pixel-data conversion parameters -% 1. retrieve face & vertex matrices from A -% 2. convert vertex matrix from data to pixels units -% 3. get xdata & ydata of hatching lines for each face -% 4. concatenate lines sandwitching nan's in between -% 5. convert xdata & ydata back to data units -% 6. plot the hatching line -% traverse if hggroup/hgtransform -if ishghandle(A,'hggroup') - if verLessThan('matlab','8.4') - H = cell(1,numel(A)); - else - H = repmat({matlab.graphics.GraphicsPlaceholder},1,numel(A)); - end - - for n = 1:numel(A.Children) - try - H{n} = newhatch(A.Children(n),opts,props); - catch - end - end - - H = [H{:}]; - return; -end -% Modify the base object property if given -if ~isempty(props) - pvalold = sethgprops(A,props); -end -try - vislisena = strcmp(opts.HatchVisible,'auto'); - if vislisena - vis = A.Visible; - else - vis = opts.HatchVisible; - end - redraw = strcmp(A.Visible,'off') && ~vislisena; - if redraw - A.Visible = 'on'; % momentarily make the patch visible - drawnow; - end - - % get the base object's vertices & faces - [V,F,FillFcns] = gethgdata(A); % object does not have its patch data ready - - if redraw - A.Visible = 'off'; % momentarily make the patch visible - end - - if ~isempty(FillFcns) - FillFcns{1}(); - drawnow; - [V,F] = gethgdata(A); % object does not have its patch data ready - FillFcns{2}(); - drawnow; - end - - % recompute hatch line data - [X,Y,Z] = computeHatchData(handle(ancestor(A,'axes')),V,F,opts); - - % 6. plot the hatching line - commonprops = {'Parent',A.Parent,'DisplayName',A.DisplayName,'Visible',vis}; - if ~strcmp(opts.HatchColor,'auto') - commonprops = [commonprops {'Color',opts.HatchColor,'MarkerFaceColor',opts.HatchColor}]; - end - if isempty(regexp(opts.HatchStyle,'speckle$','once')) - H = line(X,Y,Z,commonprops{:},'LineStyle',opts.HatchLineStyle','LineWidth',opts.HatchLineWidth); - else - H = line(X,Y,Z,commonprops{:},'LineStyle','none','Marker',opts.SpeckleMarkerStyle,... - 'MarkerSize',opts.SpeckleSize,'Parent',A.Parent,'DisplayName',A.DisplayName); - end - - if strcmp(opts.HatchColor,'auto') - syncColor(H,A); - end - - if isempty(H) - error('Unable to obtain hatching data from the specified object A.'); - end - - % 7. Move H so that it is place right above A in parent's uistack - p = handle(A.Parent); - Hcs = handle(p.Children); - [~,idx] = ismember(A,Hcs); % always idx(1)>idx(2) as H was just created - p.Children = p.Children([2:idx-1 1 idx:end]); - - % if HG1, all done | no dynamic adjustment support - if verLessThan('matlab','8.4') - return; - end - - % save the config data & set up the object listeners - setappdata(A,'HatchFill2Opts',opts); % hatching options - setappdata(A,'HatchFill2Obj',H); % hatching line object - setappdata(A,'HatchFill2LastData',{V,F}); % last patch data - setappdata(A,'HatchFill2LastVisible',A.Visible); % last sensitive properties - setappdata(A,'HatchFill2PostMarkedClean',{}); % run this function at the end of the MarkClean callback and set NoAction flag - setappdata(A,'HatchFill2NoAction',false); % no action during next MarkClean callback, callback only clears this flag - setappdata(H,'HatchFill2MatchVisible',vislisena); - setappdata(H,'HatchFill2MatchColor',strcmp(opts.HatchColor,'auto')); - setappdata(H,'HatchFill2Patch',A); % base object - - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - % Create listeners for active formatting - - addlistener(H,'ObjectBeingDestroyed',@hatchBeingDeleted); - - lis = [ - addlistener(A,'Reparent',@objReparent) - addlistener(A,'ObjectBeingDestroyed',@objBeingDeleted); - addlistener(A,'MarkedClean',@objMarkedClean) - addlistener(A,'LegendEntryDirty',@(h,evt)[])]; % <- study this later - - syncprops = {'Clipping','HitTest','Interruptible','BusyAction','UIContextMenu'}; - syncprops(~cellfun(@(p)isprop(A,p),syncprops)) = []; - for n = 1:numel(syncprops) - lis(n+2) = addlistener(A,syncprops{n},'PostSet',@syncProperty); - end - -catch ME - % something went wrong, restore the base object properties - if ~isempty(props) - for pname = fieldnames(pvalold)' - name = pname{1}; - val = pvalold.(name); - if iscell(val) - pvalold.(name){1}.(name) = pvalold.(name){2}; - else - A.(name) = pvalold.(name); - end - end - end - ME.rethrow(); -end -end -%%%%%%%%%% EVENT CALLBACK FUNCTIONS %%%%%%%%%%%% -% Base Object's listeners -% objReparent - also move the hatch object -% ObjectingBeingDestroyed - also destroy the hatch object -% MarkedClean - match color if HatchColor = 'auto' -% - check if vertex & face changed; if so redraw hatch -% - check if hatch redraw triggered the event due to object's -% face not shown; if so clear the flag -function objMarkedClean(hp,~) -% CALLBACK for base object's MarkedClean event -% check: visibility change, hatching area change, & color change -if getappdata(hp,'HatchFill2NoAction') - setappdata(A,'HatchFill2NoAction',false); - return; -end -% get the main patch object (loops if hggroup or HG2 objects) -H = getappdata(hp,'HatchFill2Obj'); -rehatch = ~strcmp(hp.Visible,getappdata(hp,'HatchFill2LastVisible')); -if rehatch % if visibility changed - setappdata(hp,'HatchFill2LastVisible',hp.Visible); - if strcmp(hp.Visible,'off') % if made hidden, hide hatching as well - if getappdata(H,'HatchFill2MatchVisible') - H.Visible = 'off'; - return; % nothing else to do - end - end -end -% get the patch data -[V,F,FillFcns] = gethgdata(hp); -if ~isempty(FillFcns) % patch does not exist, must momentarily generate it - FillFcns{1}(); - setappdata(A,'HatchFill2PostMarkedClean',FillFcns{2}); - return; -end -if ~rehatch % if visible already 'on', check for the change in object data - VFlast = getappdata(hp,'HatchFill2LastData'); - rehatch = ~isequaln(F,VFlast{2}) || ~isequaln(V,VFlast{1}); -end -% rehatch if patch data/visibility changed -if rehatch - % recompute hatch line data - [X,Y,Z] = computeHatchData(ancestor(H,'axes'),V,F,getappdata(hp,'HatchFill2Opts')); - - % update the hatching line data - set(H,'XData',X,'YData',Y,'ZData',Z); - % save patch data - setappdata(hp,'HatchFill2LastData',{V,F}); -end -% sync the color -syncColor(H,hp); -% run post callback if specified (expect it to trigger another MarkedClean -% event immediately) -fcn = getappdata(hp,'HatchFill2PostMarkedClean'); -if ~isempty(fcn) - setappdata(hp,'HatchFill2PostMarkedClean',function_handle.empty); - setappdata(hp,'HatchFill2NoAction',true); - fcn(); - return; -end -end -function syncProperty(~,evt) -% sync Visible property to the patch object -hp = handle(evt.AffectedObject); % patch object -hh = getappdata(hp,'HatchFill2Obj'); -hh.(evt.Source.Name) = hp.(evt.Source.Name); -end -function objReparent(hp,evt) -%objReparent event listener callback -pnew = evt.NewValue; -if isempty(pnew) - return; % no change? -end -% move the hatch line object over as well -H = getappdata(hp,'HatchFill2Obj'); -H.Parent = pnew; -% make sure to move the hatch line object right above the patch object -Hcs = handle(pnew.Children); -[~,idx] = ismember(hp,Hcs); % always idx(1)>idx(2) as H was just moved -pnew.Children = pnew.Children([2:idx-1 1 idx:end]); -end -function objBeingDeleted(hp,~) -%when base object is deleted -if isappdata(hp,'HatchFill2Obj') - H = getappdata(hp,'HatchFill2Obj'); - try % in case H is already deleted - delete(H); - catch - end -end -end -function hatchBeingDeleted(hh,~) -%when hatch line object (hh) is deleted -if isappdata(hh,'HatchFill2Patch') - - % remove listeners listening to the patch object - hp = getappdata(hh,'HatchFill2Patch'); - - if isappdata(hp,'HatchFill2Listeners') - delete(getappdata(hp,'HatchFill2Listeners')); - rmappdata(hp,'HatchFill2Listeners'); - end -end -end -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function varargout = computeHatchData(ax,V,F,opts) -varargout = cell(1,nargout); -if isempty(V) % if patch shown - return; -end -N = size(F,1); -XYZc = cell(2,N); -for n = 1:N % for each face - - % 2. get xdata & ydata of the vertices of the face in transformed bases - f = F(n,:); % get indices to the vertices of the face - f(isnan(f)) = []; - - [v,T,islog] = transform_data(ax,V(f,:),[]); % transform the face - if isempty(v) % face is not hatchable - continue; - end - - % 2. get xdata & ydata of hatching lines for each face - if any(strcmp(opts.HatchStyle,{'speckle','outsidespeckle'})) - xy = hatch_xy(v.',opts.HatchStyle,opts.SpeckleWidth,opts.SpeckleDensity,opts.HatchOffset); - else - xy = hatch_xy(v.',opts.HatchStyle,opts.HatchAngle,opts.HatchDensity,opts.HatchOffset); - end - - % 3. revert the bases back to 3D Eucledian space - XYZc{1,n} = revert_data(xy',T,islog).'; -end -% 4. concatenate hatch lines across faces sandwitching nan's in between -[XYZc{2,:}] = deal(nan(3,1)); -XYZ = cat(2,XYZc{:}); -% 5. convert xdata & ydata back to data units -[varargout{1:3}] = deal(XYZ(1,:),XYZ(2,:),XYZ(3,:)); -end -function tf = issupported(hbase) -% check if all of the given base objects are supported -supported_objtypes = {'patch','hggroup','bar','contour','area','surface','histogram'}; -if isempty(hbase) - tf = false; -else - tf = ishghandle(hbase,supported_objtypes{1}); - for n = 2:numel(supported_objtypes) - tf(:) = tf | ishghandle(hbase,supported_objtypes{n}); - end - tf = all(tf); -end -end -% synchronize hatching line color to the patch's edge color if HatchColor = -% 'auto' -function syncColor(H,A) -if ~getappdata(H,'HatchFill2MatchColor') - % do not sync - return; -end -if ishghandle(A,'patch') || ishghandle(A,'Bar') || ishghandle(A,'area') ... - || ishghandle(A,'surface') || ishghandle(A,'Histogram') %HG2 - pname = 'EdgeColor'; -elseif ishghandle(A,'contour') % HG2 - pname = 'LineColor'; -end -color = A.(pname); -if strcmp(color,'flat') - try - color = double(A.Edge(1).ColorData(1:3)')/255; - catch - warning('Does not support CData based edge color.'); - color = 'k'; - end -end -H.Color = color; -H.MarkerFaceColor = color; -end -function [V,F,FillFcns] = gethgdata(A) -% Get vertices & face data from the object along with the critical -% properties to observe change in the hatching area -% initialize the output variable -F = []; -V = []; -FillFcns = {}; -if ~isvalid(A) || strcmp(A.Visible,'off') - return; -end -if ishghandle(A,'patch') - V = A.Vertices; - F = A.Faces; -elseif ishghandle(A,'bar') - [V,F] = getQuadrilateralData(A.Face); -elseif ishghandle(A,'area') - [V,F] = getTriangleStripData(A.Face); - set(A,'FaceColor','none'); -elseif ishghandle(A,'surface') % HG2 - if strcmp(A.FaceColor,'none') - FillFcns = {@()set(A,'FaceColor','w'),@()set(A,'FaceColor','none')}; - return; - end - [V,F] = getQuadrilateralData(A.Face); -elseif ishghandle(A,'contour') % HG2 - - % Retrieve data from hidden FacePrims property (a TriangleStrip object) - if strcmp(A.Fill,'off') - FillFcns = {@()set(A,'Fill','on'),@()set(A,'Fill','off')}; - return; - end - [V,F] = getTriangleStripData(A.FacePrims); -elseif ishghandle(A,'histogram') %HG2: Quadrateral underlying data object - [V,F] = getQuadrilateralData(A.NodeChildren(4)); -end -end -function [V,F] = getQuadrilateralData(A) % surface, bar, histogram, -if isempty(A) - warning('Cannot hatch the face: Graphics object''s face is not defined.'); - V = []; - F = []; - return; -end -V = A.VertexData'; -% If any of the axes is in log scale, V is normalized to wrt the axes -% limits, -V(:) = norm2data(V,A); -if ~isempty(A.VertexIndices) % vertices likely reused on multiple quadrilaterals - I = A.VertexIndices; - Nf = numel(I)/4; % has to be divisible by 4 -else %every 4 consecutive vertices defines a quadrilateral - Nv = size(V,1); - Nf = Nv/4; - I = 1:Nv; -end -F = reshape(I,4,Nf)'; -if ~isempty(A.StripData) % hack workaround - F(:) = F(:,[1 2 4 3]); -end -try - if ~any(all(V==V(1,:))) % not on any Euclidian plane - % convert quadrilateral to triangle strips - F = [F(:,1:3);F(:,[1 3 4])]; - end -catch % if implicit array expansion is not supported (0, .1 dense 1 OK, 5 sparse) -% 'outspeckle',7,1 - speckled (outside) boundary of width 7 points, density 1 -% (density >0, .1 dense 1 OK, 5 sparse) -% -% -% H=M_HATCH(...) returns handles to hatches/speckles. -% -% [XI,YI,X,Y]=MHATCH(...) does not draw lines - instead it returns -% vectors XI,YI of the hatch/speckle info, and X,Y of the original -% outline modified so the first point==last point (if necessary). -% -% Note that inside and outside speckling are done quite differently -% and 'outside' speckling on large coastlines can be very slow. -% -% Hatch Algorithm originally by K. Pankratov, with a bit stolen from -% Iram Weinsteins 'fancification'. Speckle modifications by R. Pawlowicz. -% -% R Pawlowicz 15/Dec/2005 -I = zeros(1,size(xydata,2)); -% face vertices are not always closed -if any(xydata(:,1)~=xydata(:,end)) - xydata(:,end+1) = xydata(:,1); - I(end+1) = I(1); -end -if any(strcmp(styl,{'speckle','outspeckle'})) - angle = angle*(1-I); -end -switch styl - case 'single' - xydatai = drawhatch(xydata,angle,1/step,0,offset); - case 'cross' - xydatai = [... - drawhatch(xydata,angle,1/step,0,offset) ... - drawhatch(xydata,angle+90,1/step,0,offset)]; - case 'speckle' - xydatai = [... - drawhatch(xydata,45, 1/step,angle,offset) ... - drawhatch(xydata,45+90,1/step,angle,offset)]; - case 'outspeckle' - xydatai = [... - drawhatch(xydata,45, 1/step,-angle,offset) ... - drawhatch(xydata,45+90,1/step,-angle,offset)]; - inside = logical(inpolygon(xydatai(1,:),xydatai(2,:),x,y)); % logical needed for v6! - xydatai(:,inside) = []; - otherwise - xydatai = zeros(2,0); -end -end -%%% -function xydatai = drawhatch(xydata,angle,step,speckle,offset) -% xydata is given as 2xN matrix, x on the first row, y on the second -% Idea here appears to be to rotate everthing so lines will be -% horizontal, and scaled so we go in integer steps in 'y' with -% 'points' being the units in x. -% Center it for "good behavior". -% rotate first about (0,0) -ca = cosd(angle); sa = sind(angle); -u = [ca sa]*xydata; % Rotation -v = [-sa ca]*xydata; -% translate to the grid point nearest to the centroid -u0 = round(mean(u)/step)*step; v0 = round(mean(v)/step)*step; -x = (u-u0); y = (v-v0)/step+offset; % plus scaling and offsetting -% Compute the coordinates of the hatch line ............... -yi = ceil(y); -yd = [diff(yi) 0]; % when diff~=0 we are crossing an integer -fnd = find(yd); % indices of crossings -dm = max(abs(yd)); % max possible #of integers between points -% This is going to be pretty space-inefficient if the line segments -% going in have very different lengths. We have one column per line -% interval and one row per hatch line within that interval. -% -A = cumsum( repmat(sign(yd(fnd)),dm,1), 1); -% Here we interpolate points along all the line segments at the -% correct intervals. -fnd1 = find(abs(A)<=abs( repmat(yd(fnd),dm,1) )); -A = A+repmat(yi(fnd),dm,1)-(A>0); -xy = (x(fnd+1)-x(fnd))./(y(fnd+1)-y(fnd)); -xi = repmat(x(fnd),dm,1)+(A-repmat(y(fnd),dm,1) ).*repmat(xy,dm,1); -yi = A(fnd1); -xi = xi(fnd1); -% Sorting points of the hatch line ........................ -%%yi0 = min(yi); yi1 = max(yi); -% Sort them in raster order (i.e. by x, then by y) -% Add '2' to make sure we don't have problems going from a max(xi) -% to a min(xi) on the next line (yi incremented by one) -xi0 = min(xi); xi1 = max(xi); -ci = 2*yi*(xi1-xi0)+xi; -[~,num] = sort(ci); -xi = xi(num); yi = yi(num); -% if this happens an error has occurred somewhere (we have an odd -% # of points), and the "fix" is not correct, but for speckling anyway -% it really doesn't make a difference. -if rem(length(xi),2)==1 - xi = [xi; xi(end)]; - yi = [yi; yi(end)]; -end -% Organize to pairs and separate by NaN's ................ -li = length(xi); -xi = reshape(xi,2,li/2); -yi = reshape(yi,2,li/2); -% The speckly part - instead of taking the line we make a point some -% random distance in. -if length(speckle)>1 || speckle(1)~=0 - - if length(speckle)>1 - % Now we get the speckle parameter for each line. - - % First, carry over the speckle parameter for the segment - % yd=[0 speckle(1:end-1)]; - yd = speckle(1:end); - A=repmat(yd(fnd),dm,1); - speckle=A(fnd1); - - % Now give it the same preconditioning as for xi/yi - speckle=speckle(num); - if rem(length(speckle),2)==1 - speckle = [speckle; speckle(end)]; - end - speckle=reshape(speckle,2,li/2); - - else - speckle=[speckle;speckle]; - end - - % Thin out the points in narrow parts. - % This keeps everything when abs(dxi)>2*speckle, and then makes - % it increasingly sparse for smaller intervals. - dxi=diff(xi); - nottoosmall=sum(speckle,1)~=0 & rand(1,li/2)1, speckle=speckle(:,nottoosmall); end - % Now randomly scatter points (if there any left) - li=length(dxi); - if any(li) - xi(1,:)=xi(1,:)+sign(dxi).*(1-rand(1,li).^0.5).*min(speckle(1,:),abs(dxi) ); - xi(2,:)=xi(2,:)-sign(dxi).*(1-rand(1,li).^0.5).*min(speckle(2,:),abs(dxi) ); - % Remove the 'zero' speckles - if size(speckle,2)>1 - xi=xi(speckle~=0); - yi=yi(speckle~=0); - end - end -else - xi = [xi; ones(1,li/2)*nan]; % Separate the line segments - yi = [yi; ones(1,li/2)*nan]; -end -% Transform back to the original coordinate system -xydatai = [ca -sa;sa ca]*[xi(:)'+u0;(yi(:)'-offset)*step+v0]; -end -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -function [h,opts,props] = parse_input(h,argin) -% parse & validate input arguments -patchtypes = {'single','cross','speckle','outspeckle','fill','none'}; -% get base object handle -if ~issupported(h) - error('Unsupported graphics handle type.'); -end -h = handle(h); -% get common property names -pnames = getcommonprops(h); -% if style argument is given, convert it to HatchStyle option pair -stylearg = {}; -if ~isempty(argin) && ischar(argin{1}) - try - ptypes = validatestring(argin{1},patchtypes); - stylearg = {'HatchStyle' ptypes}; - argin(1) = []; - catch - % STYL not given, continue on - end -end -% create inputParser for options -p = inputParser; -p.addParameter('HatchStyle','single'); -p.addParameter('HatchAngle',45,@(v)validateattributes(v,{'numeric'},{'scalar','finite','real'})); -p.addParameter('HatchDensity',40,@(v)validateattributes(v,{'numeric'},{'scalar','positive','finite','real'})); -p.addParameter('HatchSpacing',[],@(v)validateattributes(v,{'numeric'},{'scalar','positive','finite','real'})); -p.addParameter('HatchOffset',0,@(v)validateattributes(v,{'numeric'},{'scalar','nonnegative','<',1,'real'})); -p.addParameter('HatchColor','auto',@validatecolor); -p.addParameter('HatchLineStyle','-'); -p.addParameter('HatchLineWidth',0.5,@(v)validateattributes(v,{'numeric'},{'scalar','positive','finite','real'})); -p.addParameter('SpeckleWidth',7,@(v)validateattributes(v,{'numeric'},{'scalar','finite','real'})); -p.addParameter('SpeckleDensity',100,@(v)validateattributes(v,{'numeric'},{'scalar','positive','finite','real'})); -p.addParameter('SpeckleMarkerStyle','.'); -p.addParameter('SpeckleSize',2,@(v)validateattributes(v,{'numeric'},{'scalar','positive','finite'})); -p.addParameter('SpeckleFillColor','auto',@validatecolor); -p.addParameter('HatchVisible','auto'); -for n = 1:numel(pnames) - p.addParameter(pnames{n},[]); -end -p.parse(stylearg{:},argin{:}); -rnames = fieldnames(p.Results); -isopt = ~cellfun(@isempty,regexp(rnames,'^(Hatch|Speckle)','once')) | strcmp(rnames,'ContourStyle'); -props = struct([]); -for n = 1:numel(rnames) - if isopt(n) - opts.(rnames{n}) = p.Results.(rnames{n}); - elseif ~isempty(p.Results.(rnames{n})) - props(1).(rnames{n}) = p.Results.(rnames{n}); - end -end -opts.HatchStyle = validatestring(opts.HatchStyle,patchtypes); -if any(strcmp(opts.HatchStyle,{'speckle','outspeckle'})) - warning('hatchfill2:PartialSupport','Speckle/outspeckle HatchStyle may not work in the current release of hatchfill2') -end -if strcmpi(opts.HatchStyle,'none') % For backwards compatability: - opts.HatchStyle = 'fill'; -end -opts.HatchLineStyle = validatestring(opts.HatchLineStyle,{'-','--',':','-.'},mfilename,'HatchLineStyle'); -if ~isempty(opts.HatchSpacing) - warning('HatchSpacing option has been deprecated. Use ''HatchDensity'' option instead.'); -end -opts = rmfield(opts,'HatchSpacing'); -opts.SpeckleMarkerStyle = validatestring(opts.SpeckleMarkerStyle,{'+','o','*','.','x','square','diamond','v','^','>','<','pentagram','hexagram'},'hatchfill2','SpeckleMarkerStyle'); -opts.HatchVisible = validatestring(opts.HatchVisible,{'auto','on','off'},mfilename,'HatchVisible'); -end -function pnames = getcommonprops(h) -% grab the common property names of the base objects -V = set(h(1)); -pnames = fieldnames(V); -if ishghandle(h(1),'hggroup') - pnames = union(pnames,getcommonprops(get(h(1),'Children'))); -end -for n = 2:numel(h) - V = set(h(n)); - pnames1 = fieldnames(V); - if ishghandle(h(n),'hggroup') - pnames1 = union(pnames1,getcommonprops(get(h(n),'Children'))); - end - pnames = intersect(pnames,pnames1); -end -end -function validatecolor(val) -try - validateattributes(val,{'double','single'},{'numel',3,'>=',0,'<=',1}); -catch - validatestring(val,{'auto','y','yellow','m','magenta','c','cyan','r','red',... - 'g','green','b','blue','w','white','k','black'}); -end -end -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% axes unit conversion functions -function [V,T,islog] = transform_data(ax,V,ref) -% convert vertices data to hatch-ready form -% - if axis is log-scaled, data is converted to their log10 values -% - if 3D (non-zero z), spatially transform data onto the xy-plane. If -% reference point is given, ref is mapped to the origin. Otherwise, ref -% is chosen to be the axes midpoint projected onto the patch plane. Along -% with the data, the axes corner coordinates are also projected onto the -% patch plane to obtain the projected axes limits. -% - transformed xy-data are then normalized by the projected axes spans. -noZ = size(V,2)==2; -xl = ax.XLim; -yl = ax.YLim; -zl = ax.ZLim; -% log to linear space -islog = strcmp({ax.XScale ax.YScale ax.ZScale},'log'); -if islog(1) - V(:,1) = log10(V(:,1)); - xl = log10(xl); - if ~isempty(ref) - ref(1) = log10(ref(1)); - end -end -if islog(2) - V(:,2) = log10(V(:,2)); - yl = log10(yl); - if ~isempty(ref) - ref(2) = log10(ref(2)); - end -end -if islog(3) && ~noZ - V(:,3) = log10(V(:,3)); - zl = log10(zl); - if ~isempty(ref) - ref(3) = log10(ref(3)); - end -end -if noZ - V(:,3) = 0; -end -% if not given, pick the reference point to be the mid-point of the current -% axes -if isempty(ref) - ref = [mean(xl) mean(yl) mean(zl)]; -end -% normalize the axes so that they span = 1; -Tscale = makehgtform('scale', [1/diff(xl) 1/diff(yl) 1/diff(zl)]); -V(:) = V*Tscale(1:3,1:3); -ref(:) = ref*Tscale(1:3,1:3); -% obtain unique vertices -Vq = double(unique(V,'rows')); % find unique points (sorted order) -Nq = size(Vq,1); -if Nq<3 || any(isinf(Vq(:))) || any(isnan(Vq(:))) % not hatchable - V = []; - T = []; - return; -end -try % erros if 2D object - zq = unique(Vq(:,3)); -catch - V(:,3) = 0; - zq = 0; -end -T = eye(4); -if isscalar(zq) % patch is on a xy-plane - if zq~=0 % not on the xy-plane - T = makehgtform('translate',[0 0 -zq]); - end -else - % if patch is not on a same xy-plane - - % use 3 points likely well separated - idx = round((0:2)/2*(Nq-1))+1; - - % find unit normal vector of the patch plane - norm = cross(Vq(idx(1),:)-Vq(idx(3),:),Vq(idx(2),:)-Vq(idx(3),:)); % normal vector - norm(:) = norm/sqrt(sum(norm.^2)); - - % define the spatial rotation - theta = acos(norm(3)); - if theta>pi/2, theta = theta-pi; end - u = [norm(2) -norm(1) 0]; - Trot = makehgtform('axisrotate',u,theta); - - % project the reference point onto the plane - P = norm.'*norm; - ref_proj = ref*(eye(3) - P) + Vq(1,:)*P; - if norm(3) - T = makehgtform('translate', -ref_proj); % user specified reference point or -d/norm(3) for z-crossing - end - - % apply the rotation now - T(:) = Trot*T; - - % find the axes limits on the transformed space - % [Xlims,Ylims,Zlims] = ndgrid(xl,yl,zl); - % Vlims = [Xlims(:) Ylims(:) Zlims(:)]; - % Vlims_proj = [Vlims ones(8,1)]*T'; - % lims_proj = [min(Vlims_proj(:,[1 2]),[],1);max(Vlims_proj(:,[1 2]),[],1)]; - % xl = lims_proj(:,1)'; - % yl = lims_proj(:,2)'; -end -% perform the transformation -V(:,4) = 1; -V = V*T'; -V(:,[3 4]) = []; -T(:) = T*Tscale; -end -function V = revert_data(V,T,islog) -N = size(V,1); -V = [V zeros(N,1) ones(N,1)]/T'; -V(:,end) = []; -% log to linear space -if islog(1) - V(:,1) = 10.^(V(:,1)); -end -if islog(2) - V(:,2) = 10.^(V(:,2)); -end -if islog(3) - V(:,3) = 10.^(V(:,3)); -end -end