Диаграммы
This commit is contained in:
@@ -8,24 +8,12 @@ public sealed class MinintDocument
|
|||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Delay before showing the next frame during animation playback (ms).
|
|
||||||
/// </summary>
|
|
||||||
public uint FrameDelayMs { get; set; }
|
public uint FrameDelayMs { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Document palette. Index 0 is always <see cref="RgbaColor.Transparent"/>.
|
|
||||||
/// All layers reference colors by index into this list.
|
|
||||||
/// </summary>
|
|
||||||
public List<RgbaColor> Palette { get; }
|
public List<RgbaColor> Palette { get; }
|
||||||
|
|
||||||
public List<MinintLayer> Layers { get; }
|
public List<MinintLayer> Layers { get; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reverse lookup cache: RgbaColor → palette index. Built lazily, invalidated
|
|
||||||
/// on structural palette changes (compact, clear). Call <see cref="InvalidatePaletteCache"/>
|
|
||||||
/// after bulk palette modifications.
|
|
||||||
/// </summary>
|
|
||||||
private Dictionary<RgbaColor, int>? _paletteCache;
|
private Dictionary<RgbaColor, int>? _paletteCache;
|
||||||
|
|
||||||
public MinintDocument(string name)
|
public MinintDocument(string name)
|
||||||
|
|||||||
BIN
Report/lab2/newuml/dz-a1-contrast-activity.png
Normal file
BIN
Report/lab2/newuml/dz-a1-contrast-activity.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
26
Report/lab2/newuml/dz-a1-contrast-activity.puml
Normal file
26
Report/lab2/newuml/dz-a1-contrast-activity.puml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
@startuml dz-a1-contrast-activity
|
||||||
|
title ДЗ.А1 — алгоритм ApplyContrast (по палитре документа)
|
||||||
|
|
||||||
|
start
|
||||||
|
:Вход: **MinintDocument doc**, **double factor**;
|
||||||
|
:i ← 1;
|
||||||
|
|
||||||
|
while (i < doc.Palette.Count?) is (да)
|
||||||
|
:c <- doc.Palette[i];
|
||||||
|
:doc.Palette[i] <- новый RgbaColor\n(ContrastByte для R,G,B, c.A);
|
||||||
|
:i <- i + 1;
|
||||||
|
endwhile (нет)
|
||||||
|
|
||||||
|
:doc.InvalidatePaletteCache();
|
||||||
|
|
||||||
|
floating note left
|
||||||
|
**ContrastByte(x, factor):**
|
||||||
|
v = ((x/255) - 0.5) * factor + 0.5
|
||||||
|
return Clamp( round(v * 255), 0, 255 )
|
||||||
|
--
|
||||||
|
Индекс палитры 0 не меняется.
|
||||||
|
end note
|
||||||
|
|
||||||
|
stop
|
||||||
|
|
||||||
|
@enduml
|
||||||
BIN
Report/lab2/newuml/dz-a1-grayscale-activity.png
Normal file
BIN
Report/lab2/newuml/dz-a1-grayscale-activity.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
24
Report/lab2/newuml/dz-a1-grayscale-activity.puml
Normal file
24
Report/lab2/newuml/dz-a1-grayscale-activity.puml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
@startuml dz-a1-grayscale-activity
|
||||||
|
title ДЗ.А1 — алгоритм ApplyGrayscale (по палитре документа)
|
||||||
|
|
||||||
|
start
|
||||||
|
:Вход: **MinintDocument doc**;
|
||||||
|
:i ← 1;
|
||||||
|
|
||||||
|
while (i < doc.Palette.Count?) is (да)
|
||||||
|
:c ← doc.Palette[i];
|
||||||
|
:Y ← 0.299×c.R + 0.587×c.G + 0.114×c.B + 0.5;
|
||||||
|
:gray ← (byte) Clamp((int)Y, 0, 255);
|
||||||
|
:doc.Palette[i] ← RgbaColor(gray, gray, gray, c.A);
|
||||||
|
:i ← i + 1;
|
||||||
|
endwhile (нет)
|
||||||
|
|
||||||
|
:doc.InvalidatePaletteCache();
|
||||||
|
stop
|
||||||
|
|
||||||
|
note right
|
||||||
|
Индекс палитры **0** (прозрачный) пропускается циклом.
|
||||||
|
Коэффициенты — типичная формула **яркости** (ITU-R BT.601).
|
||||||
|
end note
|
||||||
|
|
||||||
|
@enduml
|
||||||
BIN
Report/lab2/newuml/dz-a1-image-effects-classes.png
Normal file
BIN
Report/lab2/newuml/dz-a1-image-effects-classes.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
40
Report/lab2/newuml/dz-a1-image-effects-classes.puml
Normal file
40
Report/lab2/newuml/dz-a1-image-effects-classes.puml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
@startuml dz-a1-image-effects-classes
|
||||||
|
title ДЗ.А1 — сервис эффектов палитры (контраст, оттенки серого)
|
||||||
|
|
||||||
|
skinparam classAttributeIconSize 0
|
||||||
|
skinparam shadowing false
|
||||||
|
|
||||||
|
package "Minint.Core.Services" {
|
||||||
|
interface IImageEffectsService {
|
||||||
|
+ ApplyContrast(doc : MinintDocument, factor : double) : void
|
||||||
|
+ ApplyGrayscale(doc : MinintDocument) : void
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package "Minint.Core.Services.Impl" {
|
||||||
|
class ImageEffectsService {
|
||||||
|
+ ApplyContrast(doc : MinintDocument, factor : double) : void
|
||||||
|
+ ApplyGrayscale(doc : MinintDocument) : void
|
||||||
|
--
|
||||||
|
{static} - ContrastByte(value : byte, factor : double) : byte
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
package "Minint.Core.Models" <<Frame>> {
|
||||||
|
class MinintDocument {
|
||||||
|
+ Palette : List~RgbaColor~
|
||||||
|
+ InvalidatePaletteCache() : void
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IImageEffectsService <|.. ImageEffectsService : реализует
|
||||||
|
ImageEffectsService ..> MinintDocument : изменяет Palette[i],\ni = 1..Count-1
|
||||||
|
ImageEffectsService ..> MinintDocument : InvalidatePaletteCache()
|
||||||
|
|
||||||
|
note bottom of ImageEffectsService
|
||||||
|
Индекс **0** палитры (прозрачный) не меняется.
|
||||||
|
Контраст: **factor** 0 → серое, 1 → без изменений, >1 → выше контраст.
|
||||||
|
Grayscale: яркость **0,299·R + 0,587·G + 0,114·B** (округление к byte).
|
||||||
|
end note
|
||||||
|
|
||||||
|
@enduml
|
||||||
BIN
Report/lab2/newuml/dz-v1-editor-animation-flow.png
Normal file
BIN
Report/lab2/newuml/dz-v1-editor-animation-flow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
56
Report/lab2/newuml/dz-v1-editor-animation-flow.puml
Normal file
56
Report/lab2/newuml/dz-v1-editor-animation-flow.puml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
@startuml dz-v1-editor-animation-flow
|
||||||
|
title ДЗ.В1 — анимация (EditorViewModel)
|
||||||
|
|
||||||
|
skinparam shadowing false
|
||||||
|
skinparam ActivityFontSize 11
|
||||||
|
skinparam ActivityBackgroundColor #F8F8F8
|
||||||
|
|
||||||
|
start
|
||||||
|
|
||||||
|
partition PlayAnimation {
|
||||||
|
if (Container == null || Documents.Count < 2?) then (да)
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
if (IsPlaying?) then (да)
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
:IsPlaying = true;
|
||||||
|
:_animationFrameIndex = индекс ActiveDocument;
|
||||||
|
}
|
||||||
|
|
||||||
|
partition AdvanceAnimationFrame {
|
||||||
|
if (Container == null || !IsPlaying?) then (да)
|
||||||
|
:StopAnimation();
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
if (Documents.Count == 0?) then (да)
|
||||||
|
:StopAnimation();
|
||||||
|
stop
|
||||||
|
endif
|
||||||
|
:index %= Count; doc = Documents[index];
|
||||||
|
:suppress on; ActiveDocument = doc; suppress off;
|
||||||
|
:RefreshCanvasFor(doc);
|
||||||
|
:delay = max(FrameDelayMs, 10);
|
||||||
|
:новый DispatcherTimer(delay);
|
||||||
|
note right
|
||||||
|
Tick: Stop timer, index++,
|
||||||
|
снова AdvanceAnimationFrame
|
||||||
|
end note
|
||||||
|
:Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
floating note left
|
||||||
|
Цикл: каждый Tick на UI-потоке
|
||||||
|
снова вызывает AdvanceAnimationFrame.
|
||||||
|
Пауза кадра — FrameDelayMs документа.
|
||||||
|
end note
|
||||||
|
|
||||||
|
stop
|
||||||
|
|
||||||
|
legend right
|
||||||
|
StopAnimation: стоп таймера, IsPlaying=false,
|
||||||
|
SyncLayersAndCanvas. Команда Stop или
|
||||||
|
выход из Advance при ошибке состояния.
|
||||||
|
end legend
|
||||||
|
|
||||||
|
@enduml
|
||||||
BIN
Report/lab2/newuml/oz-p1-container-domain-classes.png
Normal file
BIN
Report/lab2/newuml/oz-p1-container-domain-classes.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
68
Report/lab2/newuml/oz-p1-container-domain-classes.puml
Normal file
68
Report/lab2/newuml/oz-p1-container-domain-classes.puml
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
@startuml oz-p1-container-domain-classes
|
||||||
|
title ОЗ.П1 — структура графического контейнера и представление цвета пикселя\n(модуль Minint.Core.Models)
|
||||||
|
|
||||||
|
skinparam classAttributeIconSize 0
|
||||||
|
skinparam shadowing false
|
||||||
|
|
||||||
|
class MinintContainer <<графический контейнер>> {
|
||||||
|
+ Width : int
|
||||||
|
+ Height : int
|
||||||
|
+ Documents : List~MinintDocument~ {readOnly}
|
||||||
|
+ PixelCount : int <<get>>
|
||||||
|
--
|
||||||
|
+ MinintContainer(width, height)
|
||||||
|
+ AddNewDocument(name : string) : MinintDocument
|
||||||
|
}
|
||||||
|
|
||||||
|
class MinintDocument <<кадр / документ>> {
|
||||||
|
+ Name : string
|
||||||
|
+ FrameDelayMs : uint
|
||||||
|
+ Palette : List~RgbaColor~ {readOnly}
|
||||||
|
+ Layers : List~MinintLayer~ {readOnly}
|
||||||
|
+ IndexByteWidth : int <<get>>
|
||||||
|
--
|
||||||
|
+ MinintDocument(name : string)
|
||||||
|
+ FindColorCached(color : RgbaColor) : int
|
||||||
|
+ EnsureColorCached(color : RgbaColor) : int
|
||||||
|
+ InvalidatePaletteCache() : void
|
||||||
|
}
|
||||||
|
|
||||||
|
class MinintLayer <<растровый слой>> {
|
||||||
|
+ Name : string
|
||||||
|
+ IsVisible : bool
|
||||||
|
+ Opacity : byte
|
||||||
|
+ Pixels : int[] {readOnly}
|
||||||
|
--
|
||||||
|
+ MinintLayer(name, pixelCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
class RgbaColor <<record struct,\nцвет пикселя>> {
|
||||||
|
+ R : byte
|
||||||
|
+ G : byte
|
||||||
|
+ B : byte
|
||||||
|
+ A : byte
|
||||||
|
--
|
||||||
|
{static} Transparent : RgbaColor
|
||||||
|
+ ToPackedRgba() : uint
|
||||||
|
+ ToPackedArgb() : uint
|
||||||
|
{static} FromPackedRgba(packed : uint) : RgbaColor
|
||||||
|
}
|
||||||
|
|
||||||
|
MinintContainer "1" *-- "0..*" MinintDocument : содержит
|
||||||
|
MinintDocument "1" *-- "0..*" MinintLayer : содержит
|
||||||
|
MinintDocument "1" *-- "1..*" RgbaColor : Palette
|
||||||
|
MinintLayer ..> RgbaColor : Pixels[i] — индекс\nв Palette документа
|
||||||
|
|
||||||
|
note bottom of MinintLayer
|
||||||
|
Логический «пиксель» слоя в памяти —
|
||||||
|
целочисленный **индекс** в палитре документа.
|
||||||
|
Полное описание цвета — элемент **RgbaColor**
|
||||||
|
в **MinintDocument.Palette**.
|
||||||
|
end note
|
||||||
|
|
||||||
|
note right of MinintContainer
|
||||||
|
Общие для всех документов размеры холста (**Width**, **Height**).
|
||||||
|
Число ячеек растра: **PixelCount** = Width × Height.
|
||||||
|
end note
|
||||||
|
|
||||||
|
@enduml
|
||||||
38
Report/lab2/newuml/render-png.sh
Executable file
38
Report/lab2/newuml/render-png.sh
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Rasterize PlantUML sources in this directory to PNG (ОЗ.Р1 / отчёт).
|
||||||
|
# Requires one of: plantuml in PATH, or Java + plantuml.jar (see below).
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "$SCRIPT_DIR"
|
||||||
|
|
||||||
|
# PNG рядом с исходником: oz-r1-foo.puml -> oz-r1-foo.png
|
||||||
|
OUT_OPTS=(-tpng)
|
||||||
|
|
||||||
|
run_plantuml() {
|
||||||
|
if command -v plantuml >/dev/null 2>&1; then
|
||||||
|
plantuml "${OUT_OPTS[@]}" "$@"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local jar="${PLANTUML_JAR:-}"
|
||||||
|
if [[ -n "$jar" && -f "$jar" ]] && command -v java >/dev/null 2>&1; then
|
||||||
|
java -jar "$jar" "${OUT_OPTS[@]}" "$@"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "plantuml не найден. Установите пакет (например plantuml) или задайте PLANTUML_JAR" >&2
|
||||||
|
echo " export PLANTUML_JAR=/path/to/plantuml.jar" >&2
|
||||||
|
echo "Скачать JAR: https://plantuml.com/download" >&2
|
||||||
|
return 127
|
||||||
|
}
|
||||||
|
|
||||||
|
shopt -s nullglob
|
||||||
|
sources=(*.puml)
|
||||||
|
if ((${#sources[@]} == 0)); then
|
||||||
|
echo "В $SCRIPT_DIR нет файлов *.puml" >&2
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
run_plantuml "${sources[@]}"
|
||||||
|
echo "Готово: PNG рядом с исходниками в $SCRIPT_DIR"
|
||||||
Reference in New Issue
Block a user