Downsampling and Convolution: When Can one Swap Between Them?
I thought this was because you were getting aliasing in your signal during one of the downsampling operations. However, I re-wrote your code in R (included below) and I did not see the same effect  I suspect conv is doing something odd. You may want to look at using the shape parameter and see if that makes a difference.

Below are four plots of different variants of yours:


Top left: Yours.
Top right: a variation that uses slightly different x values.
Bottom left: Yours at twice the frequency.
Bottom right: a variation that uses slightly different x values at twice the frequency.


As you can see, in all four examples the red and the black overlay exactly.



Yes, in general, these will not be the same. Below is an example with a sawtooth wave, and the two do not line up.



Here is the specific example you ask about with the triangle wave.





R Code Only Below

#43794
#N = 100;
N &lt;- 100
#dsfactor = 3;
dsfactor &lt;- 3
#H = dsfactor*3;
H &lt;- dsfactor * 3
#x = linspace(0,10,N);
x1 &lt;- seq(0,10,10/(N-1))
x2 &lt;- seq(0,10*(N-1)/N,10/N)
#y = sind(18*x);
y1 &lt;- sin(18*x1/180*pi)
y2 &lt;- sin(18*x2/180*pi)
y3 &lt;- sin(36*x1/180*pi)
y4 &lt;- sin(36*x2/180*pi)
#h = ones(H,1);
h &lt;- rep(1,H)

#convyh = conv(y,h);
convy1h &lt;- filter(y1,h)
convy2h &lt;- filter(y2,h)
convy3h &lt;- filter(y3,h)
convy4h &lt;- filter(y4,h)

downsample &lt;- function(signal, factor) 
{
  return(signal[seq(1,length(signal), factor)])
}

#convyh_ds = downsample(convyh,dsfactor)./H;
convy1h_ds &lt;- downsample(convy1h, dsfactor)/H
convy2h_ds &lt;- downsample(convy2h, dsfactor)/H
convy3h_ds &lt;- downsample(convy3h, dsfactor)/H
convy4h_ds &lt;- downsample(convy4h, dsfactor)/H
#convyh_ds3 = conv(downsample(y,dsfactor),downsample(h,dsfactor))./(ceil(H/dsfactor));
convy1h_ds3 &lt;- filter(downsample(y1,dsfactor), downsample(h,dsfactor))/ceiling(H/dsfactor)
convy2h_ds3 &lt;- filter(downsample(y2,dsfactor), downsample(h,dsfactor))/ceiling(H/dsfactor)
convy3h_ds3 &lt;- filter(downsample(y3,dsfactor), downsample(h,dsfactor))/ceiling(H/dsfactor)
convy4h_ds3 &lt;- filter(downsample(y4,dsfactor), downsample(h,dsfactor))/ceiling(H/dsfactor)
#figure;
#plot(convyh_ds,'DisplayName','downsample(conv)','LineWidth',1);
#hold on;
#plot(convyh_ds3,'DisplayName','conv(downsample)','LineWidth',1);
#grid minor
#legend('show');
#line([0 length(convyh_ds2)],[0 0],'LineStyle','--');

par(mfrow=c(2,2))
plot(convy1h_ds)
lines(convy1h_ds3, col='red')

plot(convy2h_ds)
lines(convy2h_ds3, col='red')

plot(convy3h_ds)
lines(convy3h_ds3, col='red')

plot(convy4h_ds)
lines(convy4h_ds3, col='red')