Skip to content

Comments

Implement OASIS file writer#674

Merged
yungyuc merged 1 commit intosolvcon:masterfrom
c1ydehhx:manhattan-1-delta-writer
Feb 19, 2026
Merged

Implement OASIS file writer#674
yungyuc merged 1 commit intosolvcon:masterfrom
c1ydehhx:manhattan-1-delta-writer

Conversation

@c1ydehhx
Copy link
Collaborator

@c1ydehhx c1ydehhx commented Feb 4, 2026

In this PR, I added OASIS device. This device support writer only currently. This writer implement manhattan delta format by OASIS spec.

For example, if we expected +340 for N/S direction, it will be encoded with 0xD0 0x0A0xA8 0x05, and -340 will be 0xD2 0x0A0xA9 0x05.

I added some test to make sure it work properly, and I add some edge case to make sure it will not buggy when met edge case.


Updated (2026/02/19):

After the discussion with @yungyuc, I added 3 classes modmesh::OasisWriter, modmesh::OasisRecordRect, modmesh::OasisRecordPoly to output OASIS-format bytes.

The two record classes convert geometry information into OASIS-format bytes:

  • OasisRecordPoly class accepts coordinate pairs (e.g., [[410, 720], [410, 920], [70, 920], ...]) and converts them into OASIS-format bytes.
  • OasisRecordRect class accepts a lower-left coordinate pair (e.g., [70, 800]), width, height and converts them into OASIS-format bytes.

With these record classes, OasisWriter accepts OasisRecordPoly and OasisRecordRect objects and integrates these records with the minimal required headers (e.g., magic-bytes, START, END, CELL, and CELLNAME records) and outputs OASIS-format bytes. The output bytes should be loadable by third-party software.

These classes above are wrapped as Python classes via pybind11. In this PR, I added a few unit tests to verify the classes work properly:

  • OasisRecordPoly and OasisRecordRect: verify that the produced OASIS-format bytes are correct.
  • OasisWriter: verify the output bytes contain the required headers with integrated polygon and rectangle records.

In addition, I tested the output bytes manually with KLayout software. The output bytes from OasisWriter is accepted by KLayout, as shown below.

image

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Points to address:

  • Write OASIS I/O code in C++. Name it modmesh::OasisDevice. Wrap it to Python for testing.
  • Manually verify the written file by loading it using a third-party viewer and paste the screenshot.

# POSSIBILITY OF SUCH DAMAGE.


class ManhattanDeltaCodec:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Write I/O code in C++. Python is too slow to be taken seriously for I/O.

Name it modmesh::OasisDevice for now.

from modmesh.plot import plane_layer


class ManhattanDeltaCodecTC(unittest.TestCase):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit tests for the OASIS I/O should be in Python.

@yungyuc yungyuc added the geometry Geometry entities and manipulation label Feb 4, 2026
@yungyuc yungyuc changed the title Implement Manhattan Delta Codec writer Implement OASIS file writer Feb 4, 2026
@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch from 8a2d55c to eb97718 Compare February 5, 2026 15:51
@c1ydehhx
Copy link
Collaborator Author

c1ydehhx commented Feb 5, 2026

Hi @yungyuc,
So far away, I already migrate Manhatten 1-delta writer (Named it OasisWriter) from Python to C++, and use pybind11 to wrap it as a module.

Write OASIS I/O code in C++. Name it modmesh::OasisDevice. Wrap it to Python for testing.

Done.

Manually verify the written file by loading it using a third-party viewer and paste the screenshot.

I'm concern that it will have too much diff in this PR if we want to output OASIS file. Althought we have geometry record now, we don't have some necessary OASIS header like magic bytes, START and END.

I would like to confirm that this PR should support OASIS file output or we can just test Manhatten 1-delta work properly with unit tests?

@yungyuc
Copy link
Member

yungyuc commented Feb 6, 2026

Linter did not pass. Please fix code format and then request for review again.

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some very basic points to address:

  • Do not make an intrusive alias in global namespace and for STL things like std::vector<uint8)_t>.
  • Rule of 5 for OasisDevice.
  • Name as OasisDevice::write, not writer, which is not a verb.

#include <cstdint>
#include <vector>

using bytes = std::vector<uint8_t>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not make an intrusive alias like this. It is horrible to maintain.

There is nothing wrong with using std::vector<uint8)_t>? Just spell out the type.

It is horrible to add an alias in the global name space. Unacceptable almost always.

static void append_1_delta(bytes & segment, int value);

public:
OasisDevice() = default;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule of 5.


public:
OasisDevice() = default;
static bytes writer(std::vector<int32_t> & values);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name it write, not writer, which is not a verb.

@yungyuc
Copy link
Member

yungyuc commented Feb 6, 2026

@tigercosmos @KHLee529 please help review

@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch from 71b53ff to d3e62a3 Compare February 6, 2026 15:07
namespace python
{

using namespace modmesh::oasis; // NOLINT(google-build-using-namespace)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend remove this. Namespace is important for reading the code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. modmesh::oasis namespace is not necessary and should be removed.

And, never using namespace unless it is in a very limited scope and can resolve extreme pain.


void OasisDevice::append_1_delta(std::vector<uint8_t> & segment, int value)
{
int dir_bit = value < 0 ? 1 : 0;
Copy link
Collaborator

@tigercosmos tigercosmos Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add const for all the places if applicable.

namespace oasis
{

class OasisDevice
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add document comments for classes and functions.

}
}

std::vector<uint8_t> OasisDevice::write(std::vector<int32_t> & values)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const std::vector<int32_t> & values

namespace oasis
{

void OasisDevice::append_1_delta(std::vector<uint8_t> & segment, int value)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a local function in cpp only.

while (payload >= 1)
{
int first_bit = payload >= 128 ? 1 : 0;
segment.push_back((first_bit << 7) | (payload % 128));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add comments to explain the algorithm. Including source doucment is even better.

# POSSIBILITY OF SUCH DAMAGE.


class ManhattanDeltaCodec:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove it.

device = modmesh.OasisDevice()
seg = device.writer([+340, +200, -340, -40, +300, -120, -300])

self.assertEqual(seg, [0xD0, 0x0A, 0xA0, 0x06, 0xD2,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be nice if you can explain what you try to test in the comments.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use code comments to explain.

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Points to address:

  • Do not use namespace modmesh::oasis.
  • Add very concise code comments for the key points in unit tests.

namespace python
{

using namespace modmesh::oasis; // NOLINT(google-build-using-namespace)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. modmesh::oasis namespace is not necessary and should be removed.

And, never using namespace unless it is in a very limited scope and can resolve extreme pain.

namespace modmesh
{

namespace oasis
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use namespace modmesh::oasis.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@c1ydehhx You forgot to fix it.

device = modmesh.OasisDevice()
seg = device.writer([+340, +200, -340, -40, +300, -120, -300])

self.assertEqual(seg, [0xD0, 0x0A, 0xA0, 0x06, 0xD2,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use code comments to explain.

@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch 4 times, most recently from 948efe1 to c7cec2a Compare February 8, 2026 07:55
@c1ydehhx
Copy link
Collaborator Author

c1ydehhx commented Feb 8, 2026

Hi @yungyuc and @tigercosmos.

Thanks for the review.

I complete OASIS device to store polygon and rectangle and write as OASIS format. The OASIS format will need magic-byte, START record, END record, CELLNAME record and CELL record to work. For each record, I add comment to describe its format and how to find the record spec in OASIS spec draft. I also add some comment to describe how unsigned and signed value work in OASIS. Please refer the comment in oasis_device.cpp. For the comment of tests. I leave a simple commant to let viewer refer the comment in oasis_device.cpp, which is more complete, and not leave too much words in test comment.

Also, the write() function in OASIS will return a list of bytes that represent the bytes in OASIS file. I write a simple script to check it works. The test script is not include in this PR. The script looks like:

import modmesh

device = modmesh.OasisDevice()

rec_poly = modmesh.OasisPolyRecord([
    [70, 720], [410, 720], [410, 920], [70, 920],
    [70, 880], [370, 880], [370, 760], [70, 760]])
rec_rect = modmesh.OasisRectRecord([70, 800], 180, 40)

device.add_poly_record(rec_poly)
device.add_rect_record(rec_rect)

rec_poly = modmesh.OasisPolyRecord([
    [70, 980], [410, 980], [410, 1180], [70, 1180],
    [70, 1140], [370, 1140], [370, 1020], [70, 1020]])
rec_rect = modmesh.OasisRectRecord([70, 1060], 180, 40)

device.add_poly_record(rec_poly)
device.add_rect_record(rec_rect)

with open("test.oas", "wb") as f:
    f.write(bytearray(device.write()))

It will generate test.oas file. The file in KLayout will looks like:

image

Please review it. Thanks.

class PolyRecord
{
private:
std::vector<std::pair<int, int>> vertexes;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All non-POD class member data need to prefix m_.

Put member data after member functions like other modmesh classes do. Follow convention unless you have a wonderful reason not to.

Use "vertices" as the plural form of "vertex". Do not use vertexes.

I dislike std::vector member data. But it can be here for a while. They should be changed to a pad soon.

namespace modmesh
{

namespace oasis
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@c1ydehhx You forgot to fix it.

void add_poly_record(const PolyRecord & record);
void add_rect_record(const RectRecord & record);

std::vector<uint8_t> write();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If returning a byte container, rename write to to_bytes.

* \class PolyRecord
* \brief Convert Rect information to OASIS polygon record bytes.
*/
class PolyRecord
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename PolyRecord to OasisRecordPoly.

* \class RectRecord
* \brief Convert Rect information to OASIS rectangle record bytes.
*/
class RectRecord
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename RectRecord to OasisRecordRect.

namespace oasis
{

static void append_signed_integer(std::vector<uint8_t> & segment, int value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After removing the namespace modmesh::oasis, move these free functions to OasisDevice as static functions..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You forgot to move the free functions.

import modmesh


class OasisRectRecordTC(unittest.TestCase):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good one. Need to be renamed with the C++ class.

self.assertEqual(record_bytes, list(map(ord, expected_record_bytes)))


class OasisPolyRecordTC(unittest.TestCase):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good one. Need to be renamed with the C++ class.

self.assertEqual(record_bytes, list(map(ord, expected_record_bytes)))


# For the format of OASIS, please refer OasisDevice comment in oasis_device.cpp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make it clear with the namespace modmesh::OasisDevice.

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Do not include any Python-related (pybind11 included) headers outside a pymod/ directory.

*/

#include <modmesh/base.hpp>
#include <pybind11/stl.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not import any Python-related (pybind11 included) headers outside a pymod/ directory.

@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch 2 times, most recently from 47071d4 to 51e49fc Compare February 8, 2026 10:47
@c1ydehhx
Copy link
Collaborator Author

c1ydehhx commented Feb 8, 2026

Hi @yungyuc. Thanks for the review.

I already fix all issues in comment. I adjust the function name, class name, member name, and comment that mention the class name,. Moreover, I remove pybind header that include in wrong place and remove the oasis namespace.

For the comment that move free function to OasisDevice class, since all classes depends append_signed_integer, and append_unsigned_integer function, I can't move them into OasisDevice class. However, append_magic_bytes, append_start_record_bytes, append_cell_and_cell_name_record_byte and append_end_record_byte only used in OasisDevice, I move them to OasisDevice class.

Please review it. Thanks.

@yungyuc
Copy link
Member

yungyuc commented Feb 8, 2026

For the comment that move free function to OasisDevice class, since all classes depends append_signed_integer, and append_unsigned_integer function, I can't move them into OasisDevice class.

You can. Move OasisDevice to be before the declaration of OasisRecord*, and forward declare OasisRecord* before OasisDevice. See:

// Forward declaration (but do not add comment in your PR because it's obvious.
OasisRecordPoly;
OasisRecordRect;

class OasisDevice
{

public:

  // all static functions for OasisRecord*.

private:

  std::vector<OasisRecordPoly> //...;
  std::vector<OasisRecordRect> //...;

};

class OasisRecordPoly
{
  // content.s
};

class OasisRecordRect
{
  // content.s
};

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Points to address:

  • Split the field OasisRecordRect::m_bottom_left to be m_lower and m_left.
  • Add end marker to all classes. You forgot some.
  • Missing rule of five.

static void append_end_record_byte(std::vector<uint8_t> & segment);

template <typename T>
static void append_record_bytes(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's too short to use two lines. Use a single line for the signature.

std::vector<uint8_t> to_bytes() const;

private:
std::pair<int, int> m_bottom_left;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split the field m_bottom_left to be m_lower and m_left.


private:
std::pair<int, int> m_bottom_left;
int w;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

m_ prefix. Please review carefully.

std::pair<int, int> m_bottom_left;
int w;
int h;
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class end marker.

public:
explicit OasisRecordPoly(std::vector<std::pair<int, int>> vertices)
: m_vertices(std::move(vertices)) {};
OasisRecordPoly(OasisRecordPoly const &) = default;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You forgot to delete default constructor.

, h(h)
{
}
OasisRecordRect(OasisRecordRect const &) = default;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch 2 times, most recently from 17db390 to fca59ca Compare February 8, 2026 11:35
@c1ydehhx
Copy link
Collaborator Author

c1ydehhx commented Feb 8, 2026

Hi @yungyuc. Thanks for the review.

I fix all issue mentioned in comment. I delete copy assignment on OasisDevice and record classes, add all end class marker and adjust signature to one-line, and split m_bottom_left to m_lower and m_left. Also, I check the member of non-POD class should have m_ prefix again. Sorry for the misunderstand of your instruction.

Please review it. Thanks.

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have previous points unaddressed:

  • You forgot to move free functions.
  • Missing rule of five.

@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch 2 times, most recently from 150a8c9 to f2dffb9 Compare February 8, 2026 15:21
@c1ydehhx
Copy link
Collaborator Author

c1ydehhx commented Feb 8, 2026

Hi @yungyuc. Thanks for the review.

I just move the free function into OasisDevice class, and call these function in OasisRecord* class with static way. It looks like:

std::vector<uint8_t> OasisRecordRect::to_bytes(){
    // Implementation ...
    OasisDevice::append_unsigned_integer(segment, m_w);
    OasisDevice::append_unsigned_integer(segment, m_h);
    OasisDevice::append_signed_integer(segment, m_left);
    OasisDevice::append_signed_integer(segment, m_lower);
}

Also, I delete default constructor in OasisRecord*. I previous concern that delete default constructor will happen compilation error since the vector with OasisRecord* can not be construct.

    std::vector<OasisRecordPoly> m_polygon_records;
    std::vector<OasisRecordRect> m_rect_records;

After think a while, since I don't pre-allocate the space to let the vector using default constructor to create element, it still work properly.

I already fixed these issue. Thanks.

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I delete default constructor in OasisRecord*. I previous concern that delete default constructor will happen compilation error since the vector with OasisRecord* can not be construct.

    std::vector<OasisRecordPoly> m_polygon_records;
    std::vector<OasisRecordRect> m_rect_records;

After think a while, since I don't pre-allocate the space to let the vector using default constructor to create element, it still work properly.

I already fixed these issue. Thanks.

If you want to keep the default constructor, make it explicit like:

OasisRecordPoly() = default;

Otherwise it's deleted implicitly: https://stackoverflow.com/a/38995677.

The point is to make your intention explicit. You did not seem to know that not supplying the default constructor actually removed it. It will confuse you and maintainers in the future.

  • Review if you want to have the default constructor of OasisRecord* classes or not. If yes, change the code. If not, leave a comment and stay with the deletion.

Other points to address:

  • Move the static functions to the beginning of the class because they do not depend on other code in it.

void add_poly_record(const OasisRecordPoly & record);
void add_rect_record(const OasisRecordRect & record);

static void append_signed_integer(std::vector<uint8_t> & segment, int value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I usually move the static functions to the beginning of the class because they do not depend on other code in it.

It also makes sense to move the static member functions to be before other member functions, because the latter (or the code in the latter) may call the former.

My order is usually: (1) aliases, constants, and enum, (2) static member functions, (3) member functions, (4) member data. It's also the convention used in modmesh.

Please follow the convention.

std::vector<uint8_t> to_bytes() const;

private:
int m_left;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may use 4 lines for the 4 fields or 1 line for them.

@c1ydehhx
Copy link
Collaborator Author

c1ydehhx commented Feb 9, 2026

Hi @yungyuc. Thanks for the review.

I already fix the function order of class. If my realize correct, the member function may include constructor, so I put static function before constructor. I would like to check is it fit the convention. Thanks.

For the private static function, I'm not sure the convention that also need to move to the beginning of the class. If so, it will look like this:

class OasisDevice
{
public:
    static void append_signed_integer(std::vector<uint8_t> & segment, int value);
    static void append_unsigned_integer(std::vector<uint8_t> & segment, int value);

private:
    static void append_magic_bytes(std::vector<uint8_t> & segment);
    static void append_start_record_bytes(std::vector<uint8_t> & segment);
    static void append_cell_and_cell_name_record_byte(std::vector<uint8_t> & segment);
    static void append_end_record_byte(std::vector<uint8_t> & segment);

public:
    // Public member function.

private:
    // Private member function.
    // Private member.
} /* end class OasisDevice */

Please let me know that I just keep the current version or adjust to the version above.

Moreover, I condense rect member to 1 line.

Review if you want to have the default constructor of OasisRecord* classes or not. If yes, change the code. If not, leave a comment and stay with the deletion.

After think of the while, I think I'll keep default constructor deleted. Since the empty record of poly or rect is nonsense afaik, I'll keep the default constructor deleted. Thanks for the instruction about the behavior of constructor.

These changes already co-work with Codex to check the point you address is met.

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Please let me know that I just keep the current version or adjust to the version above.

For private static functions, either works.

After think of the while, I think I'll keep default constructor deleted. Since the empty record of poly or rect is nonsense afaik, I'll keep the default constructor deleted. Thanks for the instruction about the behavior of constructor.

Not necessarily. We usually reserve in containers. But maybe reserving can use placement new. It would be interesting to check what the standard says about it.

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update commit logs and the PR leading comment with a concise summary of what you do.

You do not have to squash although you may. Request for the next review once it's done.

@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch 2 times, most recently from ef19a45 to 3c871db Compare February 10, 2026 13:37
@c1ydehhx
Copy link
Collaborator Author

c1ydehhx commented Feb 10, 2026

Hi @yungyuc. I alreday update PR description and squash the commit and add properly message.

Please merge it after CI passed. Thanks.

@yungyuc
Copy link
Member

yungyuc commented Feb 10, 2026

Hi @yungyuc. I alreday update PR description and squash the commit and add properly message.

Please squash it after CI passed. Thanks.

You already squashed. But the commit log does not have a clear summary. This is what I see:

Add OASIS device that store rect/poly and convert to OASIS format bytes

Please try again.

@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch 2 times, most recently from a7b65d9 to b60839a Compare February 10, 2026 14:01
@c1ydehhx
Copy link
Collaborator Author

Hi @yungyuc. I already rewrite the commit message that try to let it more clear. Please review it. Thanks.

@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch from b60839a to 05251c0 Compare February 10, 2026 14:05
@yungyuc
Copy link
Member

yungyuc commented Feb 10, 2026

Hi @yungyuc. I already rewrite the commit message that try to let it more clear. Please review it. Thanks.

You wrote a short commit log but it's not clear. Try this:

Add a helper class to return a byte sequence in the OASIS file format.

  • A new class, modmesh::OasisDevice, is added. The member function to_bytes() returns the byte sequence. It currently supports two OASIS record types: polygon and rectangle.
    • The returned byte sequence can be written to a file.
  • 2 new classes modmesh::OasisRecordPoly and modmesh::OasisRecordRect correspond to the supported OASIS record types.
  • The 3 new classes are wrapped to Python for testing.

Please supplement missing information and rewrite to make it more clear and concise.

Comment on lines 233 to 236
for (char c : magic_byte_plain_text)
{
segment.push_back(c);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not copy the whole buffer directly?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for all other similar operations.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will be better if I copy whole buffer directly. Thanks for the suggestion.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @tigercosmos. I changes few byte append operation with for-loop with std::vector insert operation instead, which makes the code clear. For the other byte append operation with std::vector::push_back function, I would like to append bytes sepreately and with comments to clarify how the OASIS format is organized.

@yungyuc
Copy link
Member

yungyuc commented Feb 18, 2026

@c1ydehhx Are you ready for updating the commit log?

@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch from 05251c0 to 3ba18a2 Compare February 19, 2026 00:34
@c1ydehhx
Copy link
Collaborator Author

Hi @yungyuc. Thanks for the review. I've been updated the commit message with short description summarizing what this PR does.

@yungyuc
Copy link
Member

yungyuc commented Feb 19, 2026

Hi @yungyuc. Thanks for the review. I've been updated the commit message with short description summarizing what this PR does.

Thank you, @c1ydehhx . It's still unclear and please improve.

@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch from 3ba18a2 to d14125e Compare February 19, 2026 08:27
… `modmesh::OasisRecordRect` to output OASIS-format bytes

 - `OasisRecordPoly` class accepts coordinate pairs and converts them into OASIS Polygon format bytes.
 - `OasisRecordRect` class accepts a lower-left coordinate pair, width, height and converts them into OASIS Rectangle format bytes.
 - `OasisWriter` class accepts `OasisRecordPoly` and `OasisRecordRect` objects and integrates these records with the minimal required headers (e.g., magic-bytes, START, END, CELL, and CELLNAME records).

The classes above are wrapped as Python classes via pybind11. Unit tests are added for the following classes:
 - `OasisRecordPoly` and `OasisRecordRect`: verify that the produced OASIS-format bytes are correct.
 - `OasisWriter`: verify the output bytes contain the required headers with integrated polygon and rectangle records.
@c1ydehhx c1ydehhx force-pushed the manhattan-1-delta-writer branch from d14125e to 7e3fa42 Compare February 19, 2026 08:49
@c1ydehhx
Copy link
Collaborator Author

Hi @yungyuc. Thanks for the review. I've updated the lead comment and commit message. Please review it. Thanks.

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@yungyuc yungyuc merged commit 1cf57d9 into solvcon:master Feb 19, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

geometry Geometry entities and manipulation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants