CrossDraw class
This class implements methods to plot graphical results from the Cross process of continuous beams.
Contents
Author
Luiz Fernando Martha
History
@version 1.01
Initial version (1.00): September 2022
Initially prepared for version Cross02 application of course CIV 2801 - Fundamentos de Computação Gráfica, 2022, second term, Department of Civil Engineering, PUC-Rio. Created model canvas and display of continuous beam model.
Version 1.01: September 2022
Implementation of display of deformed configuration canvas and bending moment diagram canvas. The following constant properties were added: maxbendmomsize_fac, spanmomlineshift_fac, inflectpt_fac, and rotmeter_fac. The following static methods were added: disk and rotationMeter. The following public methods were added: deformedConfig and bendingMomDiagram.
Class definition
classdef CrossDraw < handle
Public properties
properties solver = []; % handle to an object of the CrossSolver class end
Class (constant) properties
properties (Constant) supsize_fac = 0.02; % factor for support size loadsize_fac = 0.70; % factor for maximum load size in relation to % half vertical window size minloadsize_fac = 0.012 % factor for minimum load size arrowsize_fac = 0.01; % factor for load arrow size loadstep_fac = 0.05; % factor for load step dimlineshift_fac = 0.85; % factor for down shift of dimension lines % with respect to half Y size dimlinetick_fac = 0.15; % factor for dimension line tick size % with respect to half Y size maxdisplsize_fac = 0.60; % factor for maximum transversal size in % relation to half vertical window size maxbendmomsize_fac = 0.70; % factor for maximum bending moment size % in relation to half vertical window size spanmomlineshift_fac = 0.85; % factor for down shift of span moment % dimension lines with respect to half Y size inflectpt_fac = 0.005; % factor for size of inflection point disk rotmeter_fac = 0.85; % factor for rotation meter size in % relation to half vertical window size end
Private properties
properties (Access = private)
end
Constructor method
methods %------------------------------------------------------------------ function draw = CrossDraw(solver) if (nargin > 0) draw.solver = solver; end end end
Class (static) auxiliary functions
methods (Static) %------------------------------------------------------------------ % Plots a square with defined center coordinates, side length and % color. % Input arguments: % cnv: graphics context (axes) % x: center coordinate on the X axis % y: center coordinate on the Y axis % l: side length % c: color (RGB vector) function square(cnv,x,y,l,c) X = [x - l/2, x + l/2, x + l/2, x - l/2]; Y = [y - l/2, y - l/2, y + l/2, y + l/2]; fill(cnv, X, Y, c); end %------------------------------------------------------------------ % Plots a draft version of a square with defined center coordinates, % side length and color. % It draws a hollow square and sets its parent property as the % given handle to the group of graphics objects. % Input arguments: % cnv: graphics context (axes) % hnd: handle to group of graphics objects % x: center coordinate on the X axis % y: center coordinate on the Y axis % l: side length % c: color (RGB vector) function draftSquare(cnv,hnd,x,y,l,c) X = [x - l/2, x + l/2, x + l/2, x - l/2, x - l/2]; Y = [y - l/2, y - l/2, y + l/2, y + l/2, y - l/2]; plot(cnv, X, Y, 'color', c, 'Parent', hnd); end %------------------------------------------------------------------ % Plots a triangle with defined top coordinates, height, base, % orientation, and color. % Input arguments: % cnv: graphics context (axes) % x: top coordinate on the X axis % y: top coordinate on the Y axis % h: triangle height % b: triangle base % ang: angle (in radian) between the axis of symmetry and the % horizontal direction (counterclockwise) - 0 rad when % triangle is pointing left % c: color (RGB vector) function triangle(cnv,x,y,h,b,ang,c) cx = cos(ang); cy = sin(ang); X = [x, x + h * cx + b/2 * cy, x + h * cx - b/2 * cy]; Y = [y, y + h * cy - b/2 * cx, y + h * cy + b/2 * cx]; fill(cnv, X, Y, c); end %------------------------------------------------------------------ % Plots a draft version of a triangle with defined top coordinates, % height, base, orientation, and color. % It draws a hollow triangle and sets its parent property as the % given handle to the group of graphics objects. % Input arguments: % cnv: graphics context (axes) % hnd: handle to group of graphics objects % x: top coordinate on the X axis % y: top coordinate on the Y axis % h: triangle height % b: triangle base % ang: angle (in radian) between the axis of symmetry and the % horizontal direction (counterclockwise) - 0 rad when % triangle is pointing left % c: color (RGB vector) function draftTriangle(cnv,hnd,x,y,h,b,ang,c) cx = cos(ang); cy = sin(ang); X = [x, x + h * cx + b/2 * cy, x + h * cx - b/2 * cy, x]; Y = [y, y + h * cy - b/2 * cx, y + h * cy + b/2 * cx, y]; plot(cnv, X, Y, 'color', c, 'Parent', hnd); end %------------------------------------------------------------------ % Plots a circle with defined center coordinates, radius and color. % This method is used to draw hinges on 2D models. % Input arguments: % cnv: graphics context (axes) % x: center coordinate on the X axis % y: center coordinate on the Y axis % r: circle radius % c: color (RGB vector) function circle(cnv,x,y,r,c) circ = 0 : pi/50 : 2*pi; xcirc = x + r * cos(circ); ycirc = y + r * sin(circ); plot(cnv, xcirc, ycirc, 'color', c); end %------------------------------------------------------------------ % Plots a circle disk with defined center coordinates, radius and % color. The circle is filled with the given color % This method is used to inflection on 2D models. % Input arguments: % cnv: graphics context (axes) % x: center coordinate on the X axis % y: center coordinate on the Y axis % r: circle radius % c: color (RGB vector) function disk(cnv,x,y,r,c) circ = 0 : pi/50 : 2*pi; xcirc = x + r * cos(circ); ycirc = y + r * sin(circ); fill(cnv, xcirc, ycirc, c); end %------------------------------------------------------------------ % Plots an arrow with defined beggining coordinates, length, % arrowhead height, arrowhead base, orientation, and color. % This method is used to draw load symbols on 2D models. % Input arguments: % cnv: graphics context (axes) % x: beggining coordinate on the X axis % y: beggining coordinate on the Y axis % l: arrow length % h: arrowhead height % b: arrowhead base % ang: pointing direction (angle in radian with the horizontal % direction - counterclockwise) - 0 rad when pointing left % c: color (RGB vector) function arrow2D(cnv,x,y,l,h,b,ang,c) cx = cos(ang); cy = sin(ang); X = [x, x + l * cx]; Y = [y, y + l * cy]; line(cnv, X, Y, 'Color', c); CrossDraw.triangle(cnv, x, y, h, b, ang, c); end %------------------------------------------------------------------ % Plots node rotation potentiometer. % Input arguments: % cnv: graphics context (axes) % x: center coordinate on the X axis % y: center coordinate on the Y axis % r: circle radius % halfAngRange: half angle range in radians % nTicks: number of tick marks % tickSize: tick size % rotAngle: angle of rotation arrow in radians % c: color (RGB vector) function rotationMeter(cnv,x,y,r,halfAngRange,nTicks,tickSize,... rotAngle,c) if nTicks < 2 nTicks = 2; end % Draw meter arc angStep = 2*halfAngRange / 25; circ = pi/2-halfAngRange : angStep : pi/2+halfAngRange; xCirc = x + r * cos(circ); yCirc = y + r * sin(circ); plot(cnv, xCirc, yCirc, 'color', c); % Draw meter ticks tickRange = 2*halfAngRange / (nTicks-1); tickAngle = pi/2-halfAngRange; for i = 1:nTicks-1 xTick = [x + (r-tickSize) * cos(tickAngle), ... x + r * cos(tickAngle)]; yTick = [y + (r-tickSize) * sin(tickAngle), ... y + r * sin(tickAngle)]; plot(cnv, xTick, yTick, 'color', c); tickAngle = tickAngle + tickRange; end tickAngle = pi/2+halfAngRange; xTick = [x + (r-tickSize) * cos(tickAngle), ... x + r * cos(tickAngle)]; yTick = [y + (r-tickSize) * sin(tickAngle), ... y + r * sin(tickAngle)]; plot(cnv, xTick, yTick, 'color', c); % Draw meter rotation arrow arrowSize = r - 1.2*tickSize; arrowHead = r * 0.15; cx = cos(rotAngle); cy = sin(rotAngle); xtip = 0; ytip = y + arrowSize; X = [x, x + xtip*cx - ytip*cy]; Y = [y, xtip*cy + ytip*cx]; line(cnv, X, Y, 'Color', c); x1 = - arrowHead/2; y1 = + arrowSize - arrowHead; x2 = 0; y2 = y + arrowSize; x3 = + arrowHead/2; y3 = y + arrowSize - arrowHead; X = [x + x1*cx - y1*cy, x + x2*cx - y2*cy, x + x3*cx - y3*cy]; Y = [ y1*cx + x1*cy, y2*cx + x2*cy, y3*cx + x3*cy]; plot(cnv, X, Y, 'color', c); end %------------------------------------------------------------------ % Snap a value to the closest step value. function snap_val = snapToStepValue(val,step) fp = val / step; % "fraction" part ip = floor(fp); % integer part fp = fp - ip; if fp > 0.5 snap_val = (ip + 1.0) * step; elseif fp < -0.5 snap_val = (ip - 1.0) * step; else snap_val = ip * step; end end end
Protect methods
methods (Access = protected) % Access from methods in subclasses function max_load = getMaxLoad(draw) max_load = 0; for i = 1:draw.solver.nmemb if(abs(draw.solver.membs(i).q) > max_load) max_load = abs(draw.solver.membs(i).q); end end end %------------------------------------------------------------------ % Draws a continuous beam model. % Input: % - posy: Y position of continuous beam axis. % - unbalanced_node: flag for unbalanced node. % if set, display corresponding support in red color. function beam(draw,cnv,posy,unbalanced_node) len = draw.solver.totalLen; line(cnv, [0, len], [posy, posy], 'Color', [0 0 0]); %%%%%%% COMPLETE HERE - CROSSDRAW: 01 %%%%%%% end %------------------------------------------------------------------ % Draw the uniform load of a member. % Input arguments: % cnv: graphics context (axes) % init_pos: initial position of load % len: length of load % q: uniform load value % load_size: size of load % load_step: step size for drawing arrows % arrowsize: size of arrow head function memberLoad(~,cnv,init_pos,len,q,... load_size,load_step,arrowsize) %%%%%%% COMPLETE HERE - CROSSDRAW: 02 %%%%%%% end %------------------------------------------------------------------ % Draw the dimension line of a beam span. % Input arguments: % cnv: graphics context (axes) % init_pos: initial position of dimension line % len: length of dimension line % dimline_shift: down shift of dimension line % dimline_tick: size of dimension line tick function dimLine(~,cnv,init_pos,len,dimline_shift,dimline_tick) %%%%%%% COMPLETE HERE - CROSSDRAW: 03 %%%%%%% end end
Public methods
methods %------------------------------------------------------------------ % Returns the bounding box (x and y limits) of a continuous beam % model. The returned box has xmin = 0, xmax = totalLen, % ymin = -totalLen * 0.05, ymax = +totalLen * 0.05, in which % totalLen is the length of the entire beam model. % The y limits are fictitious. They are equal in module and % equal to a small percentage of the total length to force % the adjustment of the box in the y direction, keeping y = 0 % in the center of the canvas. function bbox = crossBoundBox(draw) totalLen = draw.solver.totalLen; bbox(1) = 0; bbox(2) = -totalLen * 0.05; bbox(3) = totalLen; bbox(4) = totalLen * 0.05; end %------------------------------------------------------------------ % Draws a continuous beam model with applied loads. % Input: % - cnv: graphics context (owning canvas) function model(draw,cnv) % Clear canvas cla(cnv); % Draw continuous beam without highlighting unbalanced nodes draw.beam(cnv,0,false); % Draw applied loads halfYsize = diff(cnv.YLim) * 0.5; max_load = draw.getMaxLoad(); arrowsize = draw.solver.totalLen * CrossDraw.arrowsize_fac; minload_size = draw.solver.totalLen * CrossDraw.minloadsize_fac; load_step = draw.solver.totalLen * CrossDraw.loadstep_fac; init_pos = 0; for i = 1:draw.solver.nmemb len = draw.solver.membs(i).len; load_size = CrossDraw.loadsize_fac * halfYsize * ... (abs(draw.solver.membs(i).q) / max_load); if load_size < minload_size load_size = minload_size; end q = draw.solver.membs(i).q; draw.memberLoad(cnv,init_pos,len,q,load_size,load_step,arrowsize); init_pos = init_pos + len; end % Draw dimension lines dimline_shift = halfYsize * CrossDraw.dimlineshift_fac; dimline_tick = halfYsize * CrossDraw.dimlinetick_fac; init_pos = 0; for i = 1:draw.solver.nmemb len = draw.solver.membs(i).len; draw.dimLine(cnv,init_pos,len,dimline_shift,dimline_tick); init_pos = init_pos + len; end end %------------------------------------------------------------------ % Draws a continuous beam model with its deformed configuration. % Input: % - cnv: graphics context (owning canvas) function deformedConfig(draw,cnv) % Clear canvas cla(cnv); % Draw continuous beam without highlighting unbalanced nodes draw.beam(cnv,0,false); % Initialize cross section position step vector x = linspace(0,1,50); % Get half canvas vertical size halfYsize = diff(cnv.YLim) * 0.5; % Compute size of inflection point disk mark inflectpt_size = draw.solver.totalLen * CrossDraw.inflectpt_fac; % Compute each member deformed configuration and get maximum % transversal displacement maxv = 0; % Treat first member len = draw.solver.membs(1).len; rot_ini = 0; rot_end = draw.solver.nodes(1).rot; contin_ini = draw.solver.supinit; contin_end = 1; pos_loc = x * len; loc_maxv = draw.solver.membs(1).internalDispl(... contin_ini,contin_end,rot_ini,rot_end,pos_loc); maxv = max([maxv loc_maxv]); %%%%%%% COMPLETE HERE - CROSSDRAW: 04 %%%%%%% % Compute deformed configuration display factor and % display deformed configuration. % Display inflection points: points with change of curvature, % which correspond to points in which bending moment is null. deform_fac = (CrossDraw.maxdisplsize_fac * halfYsize) / maxv; init_pos = 0; for i = 1:draw.solver.nmemb len = draw.solver.membs(i).len; pos_loc = x * len; pos_gbl = init_pos + pos_loc; displv = draw.solver.membs(i).displv * deform_fac; line(cnv, pos_gbl, displv, 'Color', [0 0 1]); [npts, ptpos] = draw.solver.membs(i).momentRoots(... draw.solver.membs(i).ml,draw.solver.membs(i).mr); F = griddedInterpolant(pos_loc,displv); vpts = F(ptpos); for j = 1:npts CrossDraw.disk(cnv,init_pos+ptpos(j),vpts(j),inflectpt_size*0.5,[0 0 1]); end init_pos = init_pos + len; end % Display node rotation meters. % Node rotation is considered equal to its tangent. % To draw node rotation in meter, compute an angle based on % a tangent value amplified by deform factor. % Rotation meter half angle range is 30 degrees. rotmeter_size = halfYsize * CrossDraw.rotmeter_fac; tick_size = rotmeter_size * 0.15; len = draw.solver.membs(1).len; node_pos = len; for i = 1:draw.solver.nnode rot = draw.solver.nodes(i).rot; noderot = atan2(rot * deform_fac,1); halfAngRange = deg2rad(30); CrossDraw.rotationMeter(cnv,node_pos,0,rotmeter_size,halfAngRange,... 7,tick_size,noderot,[0 0.5 0]); len = draw.solver.membs(i+1).len; node_pos = node_pos + len; end end %------------------------------------------------------------------ % Draws a continuous beam model with its bending moment diagram % indicating the values at the ends and the maximum value of % non-linear diagrams. % Input: % - cnv: graphics context (owning canvas) function bendingMomDiagram(draw,cnv) % Clear canvas cla(cnv); % Draw continuous beam highlighting unbalanced nodes draw.beam(cnv,0,true); % Initialize cross section position step vector x = linspace(0,1,50); % Get half canvas vertical size halfYsize = diff(cnv.YLim) * 0.5; % Compute span moment dimension line vertical shift and tick size spanmomline_shift = halfYsize * CrossDraw.spanmomlineshift_fac; spanmomline_tick = halfYsize * CrossDraw.dimlinetick_fac; % Get tolerance value for bending moments momtol = 10^-(draw.solver.decplc+1); % Compute each member bending moment diagram and get % maximum bending moment value maxm = 0; for i = 1:draw.solver.nmemb len = draw.solver.membs(i).len; pos_loc = x * len; loc_maxm = draw.solver.membs(i).bendingMoment(... draw.solver.membs(i).ml,draw.solver.membs(i).mr,... pos_loc); maxm = max([maxm loc_maxm]); end % Compute bending moment display factor and % display bending moment diagram bendmom_fac = (CrossDraw.maxbendmomsize_fac * halfYsize) / maxm; %%%%%%% COMPLETE HERE - CROSSDRAW: 05 %%%%%%% end %------------------------------------------------------------------ % Cleans data structure of a CrossSolver object. function draw = clean(draw) draw.solver = []; end end
end