You have 2 options:
- Use direct projection onto the Unit Simplex which the intersection of the 2 sets you mentioned (See Orthogonal Projection onto the Unit Simplex).
- Use Alternating Projection on each of the sets you defined.
The projection onto the Non Negative Orthant set:
$$ \operatorname{Proj}_{\mathcal{S}} \left( x \right) = \max \left\{ 0, x \right\} $$
Where $ S = \left\{ x \in \mathbb{R}^{n} \mid x \succeq 0 \right\} $;
The projection onto the set $ \mathcal{C} = \left\{ x \in \mathbb{R}^{n} \mid \boldsymbol{1}^{T} x = 1 \right\} $:
$$ \operatorname{Proj}_{\mathcal{C}} \left( x \right) = x - \frac{\sum_{i} {x}_{i} - 1}{n} \boldsymbol{1} $$
Pay attention that this is not what you had in your solution.
To show the 2 methods in practice one could use the following problem:
$$
\begin{alignat*}{3}
\arg \min_{x} & \quad & \frac{1}{2} \left\| A x - b \right\|_{2}^{2} \\
\text{subject to} & \quad & x \succeq 0 \\
& \quad & \boldsymbol{1}^{T} x = 1
\end{alignat*}
$$
The Code:
%% Solution by Projected Gradient Descent (Alternating Projections)
vX = pinv(mA) * vB;
for ii = 2:numIterations
stepSize = stepSizeBase / sqrt(ii - 1);
% Gradient Step
vX = vX - (stepSize * ((mAA * vX) - vAb));
% Projection onto Non Negative Orthant
vX = max(vX, 0);
% Projection onto Sum of 1
vX = vX - ((sum(vX) - 1) / numCols);
% Projection onto Non Negative Orthant
vX = max(vX, 0);
% Projection onto Sum of 1
vX = vX - ((sum(vX) - 1) / numCols);
% Projection onto Non Negative Orthant
vX = max(vX, 0);
% Projection onto Sum of 1
vX = vX - ((sum(vX) - 1) / numCols);
mObjVal(ii, 1) = hObjFun(vX);
end
disp([' ']);
disp(['Projected Gradient Descent (Alternating Projection) Solution Summary']);
disp(['The Optimal Value Is Given By - ', num2str(mObjVal(numIterations, 1))]);
disp(['The Optimal Argument Is Given By - [ ', num2str(vX.'), ' ]']);
disp([' ']);
%% Solution by Projected Gradient Descent (Direct Projection onto Unit Simplex)
vX = pinv(mA) * vB;
for ii = 2:numIterations
stepSize = stepSizeBase / sqrt(ii - 1);
% Gradient Step
vX = vX - (stepSize * ((mAA * vX) - vAb));
% Projection onto Unit Simplex
vX = ProjectSimplex(vX, simplexRadius, stopThr);
mObjVal(ii, 2) = hObjFun(vX);
end
disp([' ']);
disp(['Projected Gradient Descent (Direct Projection) Solution Summary']);
disp(['The Optimal Value Is Given By - ', num2str(mObjVal(numIterations, 2))]);
disp(['The Optimal Argument Is Given By - [ ', num2str(vX.'), ' ]']);
disp([' ']);
Result of a run:

As expected, the Direct Projection is faster to converge.
Also, the direct projection at each iteration generates a solution which obeys the constraint while the Alternating Projection isn't guaranteed (Though violation is really small).
The full ocde (Including solution validation with CVX) is available on my StackExchange Mathematics Q2005154 GitHub Repository (Including a direct projection onto the Unit Simplex).