添加项目

This commit is contained in:
GG Z
2026-01-01 10:02:59 +08:00
parent 1fd8d2ced7
commit 4df4ce1e6a
105 changed files with 4437 additions and 570 deletions

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB;
namespace ShrlAlgoToolkit.Core.Assists
{

View File

@@ -4,54 +4,64 @@ using Autodesk.Revit.DB;
namespace ShrlAlgoToolkit.Revit.Assists
{
internal class GeometryAssist
public class GeometryAssist
{
/// <summary>
///获取元素的包围
/// 获取多个元素的合并包围
/// </summary>
/// <param name="elements"></param>
/// <returns></returns>
public static BoundingBoxXYZ GetBoundingBox(List<Element> elements)
/// <param name="elements">元素集合</param>
/// <returns>合并后的 BoundingBoxXYZ如果集合为空或无有效包围盒则返回 null</returns>
public static BoundingBoxXYZ GetCombinedBoundingBox(IEnumerable<Element> elements)
{
if (elements == null || elements.Count == 0)
if (elements == null) return null;
double minX = double.MaxValue;
double minY = double.MaxValue;
double minZ = double.MaxValue;
double maxX = double.MinValue;
double maxY = double.MinValue;
double maxZ = double.MinValue;
bool hasValidBox = false;
foreach (var elem in elements)
{
return new BoundingBoxXYZ();
// 传入 null 表示获取模型坐标系下的包围盒
BoundingBoxXYZ box = elem.get_BoundingBox(null);
// 注意:有些元素(如某些基准面或未放置的族实例)可能返回 null
if (box == null) continue;
// 比较并更新最小值
if (box.Min.X < minX) minX = box.Min.X;
if (box.Min.Y < minY) minY = box.Min.Y;
if (box.Min.Z < minZ) minZ = box.Min.Z;
// 比较并更新最大值
if (box.Max.X > maxX) maxX = box.Max.X;
if (box.Max.Y > maxY) maxY = box.Max.Y;
if (box.Max.Z > maxZ) maxZ = box.Max.Z;
hasValidBox = true;
}
var gmax = XYZ.Zero;
var gmin = XYZ.Zero;
var elementIds = elements.Select(e => e.Id).ToList();
var doc = elements.FirstOrDefault()?.Document;
using (SubTransaction sub = new SubTransaction(doc))
{
sub.Start();
Group g;
if (doc.IsFamilyDocument)
{
g = doc.FamilyCreate.NewGroup(elementIds);
if (!hasValidBox) return null;
}
else
{
g = doc.Create.NewGroup(elementIds);
}
gmax = g.get_BoundingBox(null).Max;
gmin = g.get_BoundingBox(null).Min;
sub.RollBack();
}
return new BoundingBoxXYZ
{
Max = gmax,
Min = gmin
};
// 构造新的包围盒
BoundingBoxXYZ combinedBox = new BoundingBoxXYZ();
combinedBox.Min = new XYZ(minX, minY, minZ);
combinedBox.Max = new XYZ(maxX, maxY, maxZ);
return combinedBox;
}
/// <summary>
/// 对曲线列表进行排序,使其正确排序和定向,形成线串。
/// </summary>
public static void SortCurvesContiguous(IList<Curve> curves, bool debug_output = false)
{
const double _inch = 1.0 / 12.0;
const double _sixteenth = _inch / 16.0;
const double inch = 1.0 / 12.0;
const double sixteenth = inch / 16.0;
int n = curves.Count;
for (int i = 0; i < n; ++i)
{
@@ -71,7 +81,7 @@ namespace ShrlAlgoToolkit.Revit.Assists
// 如果匹配 end->start、
// 这是下一条曲线
if (_sixteenth > p.DistanceTo(endPoint))
if (sixteenth > p.DistanceTo(endPoint))
{
if (debug_output)
{
@@ -93,7 +103,7 @@ namespace ShrlAlgoToolkit.Revit.Assists
// 如果有匹配结果 end->end、
// 反转下一条曲线
if (_sixteenth > p.DistanceTo(endPoint))
if (sixteenth > p.DistanceTo(endPoint))
{
if (i + 1 == j)
{

View File

@@ -28,6 +28,25 @@ public static class OptionsBarAssist
}
}
public static TViewModel SetupOptionsBar<TPanel, TViewModel>()
where TViewModel : ObservableObject, new() where TPanel : Panel, new()
{
CloseOptionsBar();
var options = new TViewModel();
var view = new TPanel();
view.DataContext = options;
ShowOptionsBar(view);
return options;
}
public static void ShowInternalToolPanel()
{
if (InternalToolPanel is null)
{
return;
}
InternalToolPanel.Visibility = Visibility.Visible;
InternalToolPanel.Height = 26;
}
public static void ShowOptionsBar(FrameworkElement content)
{
if (_panelPresenter is not null)
@@ -41,19 +60,21 @@ public static class OptionsBarAssist
// actuallWidth += child.ActualWidth;
//}
_panelPresenter.Content = content;
_panelPresenter.Visibility = System.Windows.Visibility.Visible;
_panelPresenter.Visibility = Visibility.Visible;
//设为0隐藏内部的Panel
//InternalToolPanel.Height = 0;
InternalToolPanel.Height = 0;
return;
}
//第一次执行时,会创建
_panelPresenter = CreateOptionsBar();
_panelPresenter.Content = content;
//InternalToolPanel.Height = 0;
InternalToolPanel.Height = 0;
}
public static void HideOptionsBar()
/// <summary>
/// 关闭、释放
/// </summary>
public static void CloseOptionsBar()
{
if (_panelPresenter is null)
{
@@ -61,15 +82,51 @@ public static class OptionsBarAssist
}
_panelPresenter.Content = null;
_panelPresenter.Visibility = System.Windows.Visibility.Collapsed;
_panelPresenter.Visibility = Visibility.Collapsed;
InternalToolPanel.Height = 26;
}
/// <summary>
/// 隐藏
/// </summary>
public static void HideOptionsBar()
{
if (_panelPresenter is null)
{
return;
}
public static async void HideOptionsBar(TimeSpan delay)
//_panelPresenter.Content = null;
_panelPresenter.Visibility = Visibility.Collapsed;
InternalToolPanel.Height = 26;
}
/// <summary>
/// 显示
/// </summary>
public static void ShowOptionsBar()
{
if (_panelPresenter is null)
{
return;
}
//_panelPresenter.Content = null;
_panelPresenter.Visibility = Visibility.Visible;
InternalToolPanel.Height = 0;
}
public static async void CloseOptionsBarAsync(TimeSpan delay)
{
await Task.Delay(delay);
HideOptionsBar();
try
{
CloseOptionsBar();
}
catch (Exception)
{
}
}
private static ContentPresenter CreateOptionsBar()
@@ -117,9 +174,9 @@ public static class OptionsBarAssist
action(view, viewModel);
ShowOptionsBar(view);
}
catch (Exception)
catch (Exception ex)
{
throw;
MessageBox.Show(ex.Message);
}
}
}

View File

@@ -0,0 +1,520 @@
#if false
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.OpenSsl;
using OpenMcdf;
using System.Windows;
namespace ShrlAlgoToolkit.Revit.Assists;
public class PublishAssist
{
#region FileAttributes
/// <summary>
/// 设置文件为只读
/// </summary>
/// <param name="filePath"></param>
/// <param name="readOnly"></param>
public static void SetReadOnly(string filePath, bool readOnly = true)
{
try
{
if (File.Exists(filePath))
{
var info = new FileInfo(filePath);
info.IsReadOnly = readOnly;
}
else
{
Debug.WriteLine("文件不存在。");
}
}
catch (UnauthorizedAccessException)
{
Debug.WriteLine("无权限修改文件属性。");
}
catch (Exception ex)
{
Debug.WriteLine($"错误: {ex.Message}");
}
}
/// <summary>
/// 设置文件为只读
/// </summary>
/// <param name="filePath"></param>
public static void SetPrivate(string filePath)
{
try
{
if (File.Exists(filePath))
{
var info = new FileInfo(filePath);
File.SetAttributes(filePath, FileAttributes.Hidden | FileAttributes.System | FileAttributes.ReadOnly);
}
else
{
Debug.WriteLine("文件不存在。");
}
}
catch (UnauthorizedAccessException)
{
Debug.WriteLine("无权限修改文件属性。");
}
catch (Exception ex)
{
Debug.WriteLine($"错误: {ex.Message}");
}
}
#endregion
//需要与addin文件里的GUID保持一致
private static readonly Guid SchemaGuid = new Guid("A519E82B-911C-4CA5-9BC5-ED509B2055D2");
/// <summary>
/// 存储图片字节数据列表 (使用 Base64 编码)
/// </summary>
public static void StoreSignatureMap(Document doc, IDictionary<string, byte[]> signatureMap)
{
ProjectInfo projectInfo = doc.ProjectInformation;
if (projectInfo == null) return;
Schema schema = GetOrCreateSchema();
Entity entity = new Entity(schema);
IDictionary<int, string> imageMap = new Dictionary<int, string>();
try
{
IDictionary<string, string> stringMap = signatureMap
.ToDictionary(kvp => kvp.Key, kvp => Convert.ToBase64String(kvp.Value));
entity.Set<IDictionary<string, string>>("SignatureMap", stringMap);
projectInfo.SetEntity(entity);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
/// <summary>
/// 读取图片字节数据列表 (Revit 2020 兼容版, 使用 Base64 解码)
/// </summary>
public static IDictionary<string, byte[]> RetrieveSignatureMap(Document doc)
{
ProjectInfo projectInfo = doc.ProjectInformation;
var emptyDict = new Dictionary<string, byte[]>();
if (projectInfo == null) return emptyDict;
Schema schema = Schema.Lookup(SchemaGuid);
if (schema == null) return emptyDict;
Entity entity = projectInfo.GetEntity(schema);
if (entity == null || !entity.IsValid()) return emptyDict;
IDictionary<string, string> retrievedMap = entity.Get<IDictionary<string, string>>("SignatureMap");
if (retrievedMap == null) return emptyDict;
return retrievedMap.ToDictionary(kvp => kvp.Key, kvp => Convert.FromBase64String(kvp.Value));
}
/// <summary>
/// 获取或创建数据模式 (Revit 2020 兼容版)
/// </summary>
private static Schema GetOrCreateSchema()
{
Schema schema = Schema.Lookup(SchemaGuid);
if (schema == null)
{
try
{
SchemaBuilder schemaBuilder = new SchemaBuilder(SchemaGuid);
schemaBuilder.SetReadAccessLevel(AccessLevel.Application);
schemaBuilder.SetWriteAccessLevel(AccessLevel.Application);
schemaBuilder.SetVendorId("SZMC");
schemaBuilder.SetApplicationGUID(SchemaGuid);
schemaBuilder.SetSchemaName("SignatureStorage");
schemaBuilder.AddMapField("SignatureMap", typeof(string), typeof(string));
schema = schemaBuilder.Finish();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "创建schema错误");
}
}
return schema;
}
#region ExtensionsStorage
//private const string SchemaGuid = "{FBC67C54-781F-4D0A-B31B-8F54707889E0}";
///// <summary>
///// 计算hash256
///// </summary>
///// <param name="filePath"></param>
///// <returns></returns>
//public static string ComputeFileHash(string filePath)
//{
// using (SHA256 sha256 = SHA256.Create())
// using (FileStream stream = File.OpenRead(filePath))
// {
// byte[] hashBytes = sha256.ComputeHash(stream);
// return BitConverter.ToString(hashBytes).Replace("-", string.Empty).ToLower();
// }
//}
#endregion
#region PreviewSettings
/// <summary>
/// 完全替换缩略图
/// </summary>
/// <param name="rvtFilePath"></param>
/// <param name="imgPath"></param>
internal static void ReplaceThumb(string rvtFilePath, Bitmap bmp)
{
using var cf = new CompoundFile(rvtFilePath, CFSUpdateMode.Update, CFSConfiguration.Default);
// 获取根存储
CFStorage root = cf.RootStorage;
// 更新 Windows 预览
if (root.TryGetStream("RevitPreview4.0", out var previewStream))
{
using var outMs = new MemoryStream();
bmp.Save(outMs, ImageFormat.Png);
previewStream.SetData(outMs.ToArray());
}
// 更新 Revit 预览
if (root.TryGetStream("BasicFileInfo", out var basicFileInfo))
{
// 读取现有数据
byte[] data = basicFileInfo.GetData();
// 基本文件信息头部大小(版本等信息)
const int HEADER_SIZE = 0x2C8;
if (data.Length > HEADER_SIZE)
{
// 转换图片为字节数组
using (var ms = new MemoryStream())
{
// 转换为24位色
using (var temp = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format24bppRgb))
{
using (var g = Graphics.FromImage(temp))
{
g.DrawImage(bmp, 0, 0);
}
temp.Save(ms, ImageFormat.Bmp);
}
byte[] imageBytes = ms.ToArray();
// 跳过BMP文件头(14字节)和信息头(40字节)
int startIndex = 54;
// 计算新数据大小
int newDataSize = HEADER_SIZE + (imageBytes.Length - startIndex);
byte[] newData = new byte[newDataSize];
// 复制原有头部数据
Array.Copy(data, 0, newData, 0, HEADER_SIZE);
// 复制新的图像数据
Array.Copy(imageBytes, startIndex, newData, HEADER_SIZE, imageBytes.Length - startIndex);
// 写回流
basicFileInfo.SetData(newData);
}
}
}
cf.Commit();
}
/// <summary>
/// 合并图片
/// </summary>
/// <param name="thumbnail">缩略图</param>
/// <param name="overlay">图标</param>
/// <returns></returns>
internal static Bitmap CombineImages(Bitmap thumbnail, Bitmap overlay)
{
// 创建画布
Bitmap result = new Bitmap(thumbnail.Width, thumbnail.Height);
using (Graphics graphics = Graphics.FromImage(result))
{
// 绘制缩略图
graphics.DrawImage(thumbnail, 0, 0);
// 计算叠加位置(右下角)
int padding = 5;
int x = 0 + padding;
//int x = thumbnail.Width - overlay.Width - padding;
int y = thumbnail.Height - overlay.Height - padding;
// 保持图标原始大小或按比例缩放
int iconSize = 48;
var resizedOverlay = new Bitmap(overlay, iconSize, iconSize);
// 带透明度绘制
graphics.DrawImage(
resizedOverlay,
new System.Drawing.Rectangle(x, y, iconSize, iconSize),
new System.Drawing.Rectangle(0, 0, overlay.Width, overlay.Height),
GraphicsUnit.Pixel
);
}
return result;
}
/// <summary>
/// 添加水印
/// </summary>
/// <param name="rvtFilePath"></param>
/// <param name="bmp"></param>
/// <param name="watermark"></param>
internal static void AddWatermark(string rvtFilePath, Bitmap bmp, string watermark)
{
// 打开 RVT 文件的复合文件结构
using var cf = new CompoundFile(rvtFilePath, CFSUpdateMode.Update, CFSConfiguration.Default);
// 获取根存储
CFStorage root = cf.RootStorage;
// 检查是否存在 "RevitPreview4.0" 流
if (!root.TryGetStream("RevitPreview4.0", out var previewStream))
{
Debug.WriteLine("未找到 RevitPreview4.0 流。");
return;
}
// 在图像上绘制半透明文字水印
if (!string.IsNullOrEmpty(watermark))
{
using var g = Graphics.FromImage(bmp);
var font = new Font("微软雅黑", 20, System.Drawing.FontStyle.Bold);
var brush = new SolidBrush(System.Drawing.Color.FromArgb(128, System.Drawing.Color.Red));
g.DrawString(watermark, font, brush, new PointF(20, bmp.Height - 80));
}
// 将修改后的图像保存为 PNG再写回流
using var outMs = new MemoryStream();
bmp.Save(outMs, ImageFormat.Png);
previewStream.SetData(outMs.ToArray());
// 提交更改
cf.Commit();
}
#endregion
#region Hash
// 公钥(硬编码)
private const string PublicKeyPem = """
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyN+Z04RmVOvzI2Z8Li1t
xB9yv80Y4Pd+M0wiuW9BHccmVlm7LVlWDRZgaAykQxIt0UskZbaIQ5eR4mqywVoM
BygfWqurVtgC6dO3SSbhZiOuSA3g1xJLgje6TOQIPWDGw1Ap0sbWrCuk+bxPFjSi
XANksY3Qfl1e6YETYEEpptTXorM8enM4368/KkvEhFswBqE5/Qf2x7XUpPAfnh3Y
cl45bUu87yDeyAnX4HEuA+aZPHEgXFPmhndtqMiUsLEajQNd8zZQHKmjMbubAq9s
l10w7smZUck+bozHO0RP31ytI6n/7I0T9PXOb/rwjeXBxXD1K0kvU3DPuq2+a5sa
iwIDAQAB
-----END PUBLIC KEY-----
""";
// 私钥(硬编码)
private const string PrivateKeyPem = """
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAyN+Z04RmVOvzI2Z8Li1txB9yv80Y4Pd+M0wiuW9BHccmVlm7
LVlWDRZgaAykQxIt0UskZbaIQ5eR4mqywVoMBygfWqurVtgC6dO3SSbhZiOuSA3g
1xJLgje6TOQIPWDGw1Ap0sbWrCuk+bxPFjSiXANksY3Qfl1e6YETYEEpptTXorM8
enM4368/KkvEhFswBqE5/Qf2x7XUpPAfnh3Ycl45bUu87yDeyAnX4HEuA+aZPHEg
XFPmhndtqMiUsLEajQNd8zZQHKmjMbubAq9sl10w7smZUck+bozHO0RP31ytI6n/
7I0T9PXOb/rwjeXBxXD1K0kvU3DPuq2+a5saiwIDAQABAoIBAACdcETZkedzXBM5
6WofTAof4bWOgovvHJCipBgOiubPKPdG5jNq/bHX2/kSnbl2eWWMQUEuGIiYJccG
/6zF6GDQ3FqHZcNbp8M4gbymNZV0TfTB0KOTyDAaojQ381LgyIK1DcWBHdw2wCRZ
vo6v1BXez4evaUy5ckXQfAA9POiAH6Im7QQlPamaUJfBCfRqFNvTcL6YQngHg8RW
4xFvN8Lxhgnqftw0dY1YzNkDBz+toQ+211LTAJWYC4vZ2sHoGvR74YxZUWPS4wms
QdIq50kRwL45Z9IZcxqp1x27W0pEwBsOO2DhnM6r7mB7Mg9BMEjUFf3oM+vrx67W
w6McEXkCgYEA8q+Bb6ldNqWNa5uLmAziEqXCnN/X9o1Cr81YIeWZpx4Ovx2aR3wH
4OtWl9VmYrU7w758nhPH27q8ADxjSbIB3ShPPdfLcKBoW/5eg+K8Bexr5Fb6Lyqo
SMhFLptxOdNzYLej99XppzRk4CV3s7IZsfQd6okSdfvlqka5ExFjXDkCgYEA0+TZ
IBsc0nCZFTlcDxxMCkmj+c4+c01BGgSeoVSKIgyp5d5DSZoNjxXsrP3Nw3uq2+fh
v4DD/V76BpzQ6v7P+Xg9YbW1QO6QdsG4Cf1bnAFYaTwQwdm2To5SXixYpVnON4Xv
4fOWVL0qrn3PK6aUTJCcEOdhx1YtBl+P4gVq9OMCgYEAhtLcDOXBhE96/rI+Xi2i
FwwBz1dISo/14WcqNEKzFzXKqYBPqrEMS3dS9y02IVZgKoIUB1oj6T2XnmXuHw4G
nQ/83fWZ7ysebyUk6w42uO+8jPGJMlT3gt/IF3mB8Mc5TR0YueIcWajw9dm645jp
T4S4bgjSubtEv1FlFmPNmHkCgYAtmq5ka5FrdVJtL/gxRFzVRf4lsI7eT/039VCS
1lgYdfNHBuwidiZ+6jATF1jmvsIKLED472S/LmbPb4bDXO4z+f3z/qCxBedPt+e9
Nqs1y1BU7dmJbyr+g0EVBaRaihaI+qmjTsLHICOEhI1HDsYSKHl+Zd40gcaU/ZJB
Cft4EwKBgQDeK/3k6OJTPuzskuqMsQy6yHd7hesxvdsfUH78tZrkRB2B9fciOa2v
ulfBss9KKVCQeKaC+91ptLpMOlSJhc9tZUsWvE19vVlNmN0ezQyfSFn+E09Ouqin
0cMfedRgHigwi+T818aFnC8qPzTMqCMQyxRTYxEC43OB9VcPyzo1yA==
-----END RSA PRIVATE KEY-----
""";
private static AsymmetricKeyParameter GetPublicKey()
{
using var reader = new StringReader(PublicKeyPem);
var pemReader = new PemReader(reader);
return (AsymmetricKeyParameter)pemReader.ReadObject();
}
private static AsymmetricKeyParameter GetPrivateKey()
{
using var reader = new StringReader(PrivateKeyPem);
var pemReader = new PemReader(reader);
var keyPair = (AsymmetricCipherKeyPair)pemReader.ReadObject();
return keyPair.Private;
}
private static byte[] ComputeFileHash(string filePath)
{
using var sha256 = SHA256.Create();
using var stream = File.OpenRead(filePath);
return sha256.ComputeHash(stream);
}
private static byte[] EncryptData(byte[] data, AsymmetricKeyParameter publicKey)
{
var rsaEngine = new Org.BouncyCastle.Crypto.Engines.RsaEngine();
rsaEngine.Init(true, publicKey);
return rsaEngine.ProcessBlock(data, 0, data.Length);
}
private static byte[] DecryptData(byte[] encryptedData, AsymmetricKeyParameter privateKey)
{
var rsaEngine = new Org.BouncyCastle.Crypto.Engines.RsaEngine();
rsaEngine.Init(false, privateKey);
return rsaEngine.ProcessBlock(encryptedData, 0, encryptedData.Length);
}
private static readonly string EncryptFileName = ".hashes.enc";
/// <summary>
/// 获取相对路径
/// </summary>
/// <param name="relativeTo">相对于某个目录</param>
/// <param name="path">示例路径</param>
/// <returns></returns>
private static string GetRelativePath(string relativeTo, string path)
{
// 确保路径以目录分隔符结尾(对于目录路径)
string from = Path.GetFullPath(relativeTo).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar;
string to = Path.GetFullPath(path);
Uri fromUri = new Uri(from);
Uri toUri = new Uri(to);
// 计算相对 URI
Uri relativeUri = fromUri.MakeRelativeUri(toUri);
// 将相对 URI 转换回字符串,并替换可能的 '/' 为当前平台的分隔符
string relativePath = Uri.UnescapeDataString(relativeUri.ToString()).Replace('/', Path.DirectorySeparatorChar);
return relativePath;
}
public static string GenerateEncFile(string directoryPath)
{
var publicKey = GetPublicKey();
var files = Directory.GetFiles(directoryPath, "*.rvt", SearchOption.AllDirectories);
var encFilePath = Path.Combine(directoryPath, EncryptFileName);
using var fs = new FileStream(encFilePath, FileMode.Create, FileAccess.Write);
using var bw = new BinaryWriter(fs);
foreach (var file in files)
{
//var fileName = Path.GetFileName(file);
var fileName = GetRelativePath(directoryPath, file);
var fileHash = ComputeFileHash(file);
var nameBytes = Encoding.UTF8.GetBytes(fileName);
var combined = nameBytes.Concat(fileHash).ToArray();
var encrypted = EncryptData(combined, publicKey);
bw.Write(nameBytes.Length);
bw.Write(nameBytes);
bw.Write(encrypted.Length);
bw.Write(encrypted);
}
return encFilePath;
}
public static StringBuilder VerifyEncFile(string directoryPath, out bool hasModified)
{
hasModified = false;
var privateKey = GetPrivateKey();
var encFilePath = Path.Combine(directoryPath, EncryptFileName);
StringBuilder sb = new StringBuilder();
if (!File.Exists(encFilePath))
{
sb.AppendLine("验证文件未找到。");
return sb;
}
Dictionary<string, string> allFiles;
try
{
//转成相对路径
allFiles = Directory.GetFiles(directoryPath, "*.rvt", SearchOption.AllDirectories)
.ToDictionary(
file => GetRelativePath(directoryPath, file),
file => file,
StringComparer.OrdinalIgnoreCase);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "验证出错!", MessageBoxButton.OK, MessageBoxImage.Error);
return sb;
}
using var fs = new FileStream(encFilePath, FileMode.Open, FileAccess.Read);
using var br = new BinaryReader(fs);
while (fs.Position < fs.Length)
{
var nameLen = br.ReadInt32();
//if (nameLen <= 0 || nameLen > 256) // 假设文件名长度不超过256字节
//{
// Console.WriteLine("无效的文件名长度。");
// continue;
//}
var nameBytes = br.ReadBytes(nameLen);
var fileName = Encoding.UTF8.GetString(nameBytes);
var encLen = br.ReadInt32();
var encrypted = br.ReadBytes(encLen);
if (!allFiles.TryGetValue(fileName, out var actualFilePath))
{
sb.AppendLine($"{fileName} 未找到");
continue;
}
var decrypted = DecryptData(encrypted, privateKey);
var expectedName = Encoding.UTF8.GetString(decrypted, 0, nameBytes.Length);
var expectedHash = decrypted.Skip(nameBytes.Length).ToArray();
var currentHash = ComputeFileHash(actualFilePath);
bool match = expectedName == fileName && currentHash.SequenceEqual(expectedHash);
if (!match)
{
hasModified = true;
sb.AppendLine($"{fileName}");
}
}
return sb;
}
#endregion
}
#endif

View File

@@ -168,7 +168,7 @@ public static class SpatialAssist
//container.Add(mergeList); // 添加最后的合并列表
return container;
}
public static Transform GetProfileTranform(Curve referCurve)
public static Transform GetProfileTransform(Curve referCurve)
{
//非刚性变换,会改变原几何,此变换在曲线计算导数时为非刚性变换各个basis的模不等于1
var point = referCurve.GetEndPoint(0);
@@ -292,145 +292,6 @@ public static class SpatialAssist
return allChains;
}
///// <summary>
///// 连成线串
///// </summary>
///// <param name="initCurve"></param>
///// <param name="sourceCurves"></param>
//private static void SortOpenedContinuousCurves(Curve initCurve, List<Curve> sourceCurves)
//{
// if (sourceCurves == null)
// {
// return;
// }
// //if (sourceCurves.Count <= 2)
// //{
// // return;
// //}
// var start = initCurve.GetEndPoint(0);
// var end = initCurve.GetEndPoint(1);
// //curvesSorted.Add(initCurve);
// sourceCurves.Remove(initCurve);
// for (var i = sourceCurves.Count - 1; i >= 0; i--)
// {
// if (sourceCurves.Count == 0)
// {
// break;
// }
// if (i >= sourceCurves.Count)
// {
// i = sourceCurves.Count - 1;
// }
// //var anotherCurve = sourceCurves[i];
// var comparisonR = initCurve.Intersect(sourceCurves[i], out var _);
// //圆
// if (comparisonR == SetComparisonResult.Disjoint && initCurve is Arc && sourceCurves[i] is Arc)
// {
// var curves = new List<Curve>() { initCurve, sourceCurves[i] };
// try
// {
// var loop = CurveLoop.Create(curves);//如果报错,说明两个半圆没形成圆,是不连续的;
// _curvesSorted = curves;
// //移除当前的线段
// sourceCurves.Remove(sourceCurves[i]);
// return;
// }
// catch (Exception)
// {
// }
// }
// if (SetComparisonResult.Overlap == comparisonR)
// {
// //XYZ point = null;
// //if (intersectionR != null && !intersectionR.IsEmpty)
// //{
// // point = intersectionR.get_Item(0).XYZPoint;
// //}
// var start1 = sourceCurves[i].GetEndPoint(0);
// var end1 = sourceCurves[i].GetEndPoint(1);
// if (end.IsAlmostEqualTo(start1))//顺序连接
// {
// _curvesSorted.Add(sourceCurves[i]);
// }
// if (end.IsAlmostEqualTo(end1))//终点一样,反向加到后面
// {
// sourceCurves[i] = sourceCurves[i].CreateReversed();//替换掉,才能保证移除的对象是同一个
// _curvesSorted.Add(sourceCurves[i]);
// }
// if (start.IsAlmostEqualTo(start1))//起点一样,反向插到前面
// {
// sourceCurves[i] = sourceCurves[i].CreateReversed();
// _curvesSorted.Insert(_curvesSorted.IndexOf(initCurve), sourceCurves[i]);
// }
// if (start.IsAlmostEqualTo(end1))//顺序连接,但是在前面
// {
// _curvesSorted.Insert(_curvesSorted.IndexOf(initCurve), sourceCurves[i]);
// }
// SortOpenedContinuousCurves(sourceCurves[i], sourceCurves);
// }
// }
//}
/// <summary>
/// 转线串
/// </summary>
/// <param name="curves"></param>
/// <returns></returns>
//public static List<List<Curve>> ToCurveLoops(List<Curve> curves)
//{
// List<List<Curve>> list = [];
// while (curves.Any())
// {
// _curvesSorted =
// [
// curves[0]
// ];
// if (!curves[0].IsBound)
// {
// curves.Remove(curves[0]);
// list.Add(_curvesSorted);
// continue;
// }
// SortOpenedContinuousCurves(curves[0], curves);
// list.Add(_curvesSorted);
// }
// //for (var i = 0; i < 100; i++)
// //{
// // try
// // {
// // if (!curves.Any())
// // {
// // break;
// // }
// // _curvesSorted = new()
// // {
// // curves[0]
// // };
// // if (!curves[0].IsBound)
// // {
// // curves.Remove(curves[0]);
// // list.Add(_curvesSorted);
// // continue;
// // }
// // SortOpenedContinuousCurves(curves[0], curves);
// // }
// // catch (Exception ex)
// // {
// // Debug.Write(ex.StackTrace);
// // }
// // list.Add(_curvesSorted);
// // if (!curves.Any())
// // {
// // break;
// // }
// //}
// return list;
//}
}
public interface ICurveContainer